Формирует элементы! Они боль в стиле, не так ли? Заманчиво полностью заменить их на какую-то пользовательскую разметку и CSS нашего собственного дизайна. Беда в том, что у получающегося в результате крысиного гнезда div
span
type="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"
Это потребует атрибута tabindex
checked
Я даже не собираюсь идти по этому пути.
То, что я сделал, доступно в виде демонстрационной версии 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-shadow
border-radius
label
Поддержка селектора может быть заполнена такой библиотекой, как 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?