Узнайте, как создавать настраиваемые доступные radio и checkbox в CSS, которые идеально совпадают с их метками.
Создание настраиваемых radio/checkbox - непростая задача. Они должны быть доступными, легко настраиваемыми и идеально согласованными с этикетками.
HTML
Важное правило, которого я стараюсь придерживаться при создании компонентов, - начинать с простейшей структуры и добавлять дополнительные элементы (например, обертывание родителей) только в случае необходимости.
Вот все, что нам нужно для кнопок radio и checkbox:
<!-- radio button -->
<div>
<input class="radio" type="radio" name="radio-button" id="radio-1">
<label for="radio-1">Choice 1</label>
</div>
<!-- checkbox button -->
<div>
<input class="checkbox" type="checkbox" id="checkbox-1">
<label for="checkbox-1">Option 1</label>
</div>
Структура HTML идентична той, которую мы использовали бы с собственными кнопками, за исключением того, что мы добавляем класс .radio
/ .checkbox
к вводу.
CSS
Шаг 1 - визуально скрыть нативные кнопки:
.radio,
.checkbox {
position: absolute;
margin: 0 !important;
padding: 0 !important;
opacity: 0;
height: 0;
width: 0;
pointer-events: none;
}
Если вы не установите значения top
/ right
/ bottom
/ left
для элементов абсолютной позиции, они удаляются из потока, но не перемещаются. Это важно, потому что в противном случае их положение будет непредсказуемым и может привести к прокрутке вверх страницы при нажатии кнопок.
Затем мы собираемся использовать +
(соседний комбинатор-близнец) для нацеливания и стилизации меток и их псевдоэлементов ::before
(настраиваемые кнопки):
.radio + label,
.checkbox + label {
user-select: none;
cursor: pointer;
line-height: 1.4;
}
.radio + label::before,
.checkbox + label::before {
content: '';
display: inline-block;
width: 18px;
height: 18px;
background-color: #FFF;
border: 2px solid #DBDBDB;
margin-right: 10px;
transition: .2s;
}
.radio + label::before {
border-radius: 50%;
}
.checkbox + label::before {
border-radius: 4px;
}
На этом этапе мы можем создать некоторые настраиваемые свойства CSS. Преимущество этого заключается в том, что позже настройка будет намного проще, если мы решим изменить кнопки: мы можем просматривать и обновлять переменные, а не проверять весь CSS.
Мы собираемся настроить таргетинг на проверенный статус входов и применить стиль к псевдоэлементам меток:
.radio:checked + label::before,
.checkbox:checked + label::before {
background-color: #1a73e8;
box-shadow: none;
border-color: #1a73e8;
transition: transform 0.2s;
}
.radio:active + label::before,
.checkbox:active + label::before {
transform: scale(0.8);
transition: transform 0.2s;
}
.radio:checked:active + label::before,
.checkbox:checked:active + label::before {
transform: none;
transition: none;
}
.radio:checked + label::before {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg class='nc-icon-wrapper' fill='%23ffffff'%3E%3Ccircle cx='8' cy='8' r='8' fill='%23ffffff'%3E%3C/circle%3E%3C/g%3E%3C/svg%3E");
background-size: 10px;
}
.checkbox:checked + label::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpolyline points='1 6.5 4 9.5 11 2.5' fill='none' stroke='%23FFFFFF' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'/%3E%3C/svg%3E");
background-size: 10px;
}
Мы используем свойство background-image
для добавления маркеров SVG (через URI данных). Преимущество этого метода заключается в том, что вы можете настроить толщину значка (stroke-width = '2'
) и его цвет (stroke='%23FFFFFF'
) в CSS.
Что у нас есть на данный момент:
Выравнивание
А вот и самая сложная часть: совместить кнопки переключателей / флажков с их метками.
Сначала установите свойство display
метки равным inline-flex
и align-items
равным flex-start
:
.radio + label,
.checkbox + label {
display: inline-flex;
align-items: flex-start;
line-height: 32px;
}
.radio + label::before,
.checkbox + label::before {
flex-shrink: 0;
margin-right: 10px;
}
Таким образом, мы устранили проблему выравнивания по левому краю, видимую, когда метка разбивается на несколько строк, и мы выровняли кнопки и метки по вертикали вверху:
Чтобы выровнять кнопки и метки по вертикали, нам нужно вычислить высоту метки, которая равна размеру шрифта, умноженному на высоту строки.
Вычисленное значение font-size
для метки непредсказуемо (например, мы могли бы изменить его с помощью служебных классов), но для псевдоэлемента label ::before
этот font-size
всегда будет равен 1em
!
Зная высоту, мы можем использовать формулу для нажатия настраиваемых кнопок переключателя / флажка на очень конкретную величину, которая выравнивает их с первой строкой метки. 🤯
.radio + label::before,
.checkbox + label::before {
position: relative;
top: 1em;
}
Больше никаких случайных и непредсказуемых уловок с отрицательной маржой! 🎉
Доступность
Поскольку мы не создали никаких настраиваемых элементов, компонент доступен, и программы чтения с экрана должным образом сообщают об этом.
Однако не забудьте включить эффект: focus
(собственные кнопки не видны):
.radio:focus + label::before,
.checkbox:focus + label::before {
border-color: #1a73e8;
box-shadow: 0 0 0 3px rgba(26, 115, 232, .3);
}
Просмотр окончательного результата:
Выполнено! 🎉
Ссылка на автора - twitter.com/guerriero_se !