Формирует элементы!  Они боль в стиле, не так ли?  Заманчиво полностью заменить их на какую-то пользовательскую разметку и CSS нашего собственного дизайна.  Беда в том, что у получающегося в результате крысиного гнезда divspantype="radio" 
 <div class="radio-label">
  <div class="radio-input" data-checked="false" data-value="accessible"></div>
  accessibility?
</div>
Это всего лишь одинокий фрагмент текста с надписью «доступность». Действительно, трагично. Чтобы это снова начало работать правильно, нам нужно добавить все виды исправительной семантики WAI-ARIA. В бессмертных словах Iron Maiden: « Могу ли я играть с безумием? »
 <div class="radio-label" id="accessible-radio">
  <div class="radio-input" data-checked="false" data-value="accessible" 
       aria-labelledby="accessible-radio" role="checkbox" aria-checked="false">
  </div>
  accessibility?
</div>
  Наш пример все еще на сто процентов недоступен, потому что нам еще предстоит обойти все обычные поведения и привязки клавиш, установленные стандартным type="radio"  Это потребует атрибута tabindexchecked  Я даже не собираюсь идти по этому пути. 
То, что я сделал, доступно в виде демонстрационной версии CodePen , и последующее объяснение этой методики.
Примечание. Если вы ранее не использовали радиокнопки на клавиатуре, знайте, что вы можете сфокусировать активную кнопку с помощью клавиши TAB и изменить активную кнопку с помощью клавиш со стрелками ВВЕРХ и ВНИЗ. Это стандартное поведение UA, а не эмуляция JavaScript.
Используйте то, что уже есть
Чтобы мыслить доступно, вы должны рассматривать HTML как интерфейс, а CSS — только внешний вид этого интерфейса; брендинг. Соответственно, нам нужно искать способы взять под контроль эстетику пользовательского интерфейса, не полагаясь на воссоздание базовой разметки, которая знаменует собой отход от стандартов.
Что мы знаем о радиокнопках?
  Одна вещь, которую мы знаем о переключателях, это то, что они могут быть либо в проверенном, либо в нерабочем состоянии.  Не берите в голову ARIA, это просто <label for="accessible">
  <input type="radio" value="accessible" name="quality" id="accessible"> accessible
</label>
<label for="pretty">
  <input type="radio" value="pretty" name="quality" id="pretty"> pretty
</label>
<label for="accessible-and-pretty">
  <input type="radio" value="pretty"
         name="quality" id="accessible-and-pretty" checked> accessible and pretty
</label> 
 :checked
  К счастью, мы можем выразить проверенное состояние через псевдокласс [type="radio"]:checked { 
   /* styles here */
}
 [type="radio"]:checked + span {
   /* styles for a span proceeded by a checked radio button */
}
Менее удачно, что в этом блоке не так много свойств, которые можно было бы почитать, особенно не всегда в разных браузерах. Радиокнопки упрямо отказываются подчиняться нашей воле.
Соседний братский комбинатор
Я люблю соседний братский комбинатор со страстью, которую мужчина, возможно, не должен резервировать для выражений селектора CSS. Это позволяет мне стилизовать элементы в соответствии с природой предшествующих им элементов.
Это мощное понятие в отношении наших радиокнопок, потому что оно позволяет нам отложить появление изменений состояния на элементы, которые на самом деле можно легко стилизовать.
 span
Нам, конечно, придется добавить элементы разметки в разметку, но хуже HTML может стать и HTML.
 <fieldset>
  <legend>Radio Control Quality</legend>
  <label for="accessible">
    <input type="radio" value="accessible" name="quality" id="accessible"> 
    <span>accessible</span>
  </label>
  <label for="pretty">
    <input type="radio" value="pretty" name="quality" id="pretty"> 
    <span>pretty</span>
  </label>
  <label for="accessible-and-pretty">
    <input type="radio" value="pretty" name="quality" id="accessible-and-pretty" checked> 
    <span>accessible and pretty</span>
  </label>
</fieldset>
  Мы не хотим на самом деле стилизовать текст метки, но мы создали необходимые отношения, чтобы отодвинуть визуальную обратную связь от <input>  Стилизация переключателя будет фактически отложена <span>::before[type="radio"] { 
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px; margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}
Скрытие переключателя — это всего лишь случай использования доступной техники сокрытия, подобной той, что есть в CSS HTML5 Boilerplate :
 <label>
  Но если он скрыт, как кто-нибудь может щелкнуть по нему?  Вложив переключатель в <label>[type="radio"] + span::before {  В любом случае, это хорошая техника, потому что она увеличивает «зону попадания» в противном случае уменьшительного контроля. 
  content: '';
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.25em;
  border-radius: 1em;
  border: 0.125em solid #fff;
  box-shadow: 0 0 0 0.15em #000;
  margin-right: 0.75em;
  transition: 0.5s ease all;
}
Стиль
Как упоминалось ранее, мы будем использовать псевдоконтент для подделки нашей «радиокнопки». Таким образом, мы можем обрабатывать стиль текста метки отдельно.
 border
  Обратите внимание на использование box-shadow[type="radio"]:checked + span::before {  Выбранный стиль впоследствии изменяет разброс радиуса тени блока и включает зеленый на / правильный / выбранный / положительный цвет;  вид, который обычно определяется где-то в ваших переменных Sass. 
  background: green;
  box-shadow: 0 0 0 0.25em #000;
}
 outline
Никогда не забывай
  Осталось только включить стиль фокуса, чтобы пользователи клавиатуры могли видеть, какой элемент находится под их контролем.  thin dotted<span>::after[type="radio"]:focus + span::after {  Эта визуальная обратная связь более убедительна, чем поставщики браузеров по умолчанию, помогая повысить доступность состояния фокуса. 
  content: '\0020\2190';
  font-size: 1.5em;
  line-height: 1;
  vertical-align: -0.125em;
}
 checked
IEH8
  IE8 создает проблему, потому что он не поддерживает ни box-shadowborder-radiuslabel  Поддержка селектора может быть заполнена такой библиотекой, как Selectivizr, а стили могут обрабатываться по-разному (возможно, фоновое изображение?), Но моя предпочтительная стратегия, вероятно, заключалась бы в использовании постепенной деградации.  Sass или LESS могут кратко изолировать проблемные блоки объявлений. 
  Обратите внимание, что улучшения для cursor: pointer/* One radio button per line */
label {
  display: block;
  cursor: pointer;
  line-height: 2.5;
  font-size: 1.5em;
}
:not(.lt-ie9) {
    /* HTML5 Boilerplate accessible hidden styles */
    [type="radio"] {
      border: 0;
      clip: rect(0 0 0 0);
      height: 1px; margin: -1px;
      overflow: hidden;
      padding: 0;
      position: absolute;
      width: 1px;
    }
    [type="radio"] + span {
      display: block;
    }
    /* the basic, unchecked style */
    [type="radio"] + span::before {
      content: '';
      display: inline-block;
      width: 1em;
      height: 1em;
      vertical-align: -0.25em;
      border-radius: 1em;
      border: 0.125em solid #fff;
      box-shadow: 0 0 0 0.15em #000;
      margin-right: 0.75em;
      transition: 0.5s ease all;
    }
    /* the checked style using the :checked pseudo class */
    [type="radio"]:checked + span::before {
      background: green;
      box-shadow: 0 0 0 0.25em #000;
    }
    /* never forget focus styling */
    [type="radio"]:focus + span::after {
      content: '\0020\2190';
      font-size: 1.5em;
      line-height: 1;
      vertical-align: -0.125em;
    }
} 
 checkbox
Вывод
Вот оно, решение для радиоуправляемых тем, которое использует все это…
- HTML
- CSS
… и ничего из этого:
- JavaScript
- WAI-ARIA
- Колесо изобретать
- шаман
Естественно, базовая техника может быть применена и к элементам управления флажками, но вы должны помнить о дизайне чеков (тиков). Так что ты думаешь? Простой юникод? Иконка шрифта? Фоновая картинка? Или, может быть, форма, созданная полностью в CSS?