Стилизация чекбоксов и радиокнопок на чистом CSS с совместимостью для старых браузеров

Честно говоря, я «слегка» припозднился с данной статьей, т.к. то, что в ней изложено, можно было применять на практике уже довольно давно. Но лучше поздно, чем никогда, тем более, что я уверен, что среди моих читателей найдутся и те, кто не пользуется этим способом при верстке по тем или иным причинам, как, собственно, и я до недавнего времени.

Для того, чтобы оформить чекбоксы и радиокнопки, как того требует дизайн, сегодня не обязательно использовать JavaScript-решения (типа моего плагина jQuery Form Styler), т.к. для этого можно задействовать чистый CSS, причем с обратной совместимостью для старых браузеров (т.е. не в ущерб юзабилити), которые не поддерживают современные CSS-правила.

Другими словами — в современных браузерах чекбоксы и радиокнопки будут выглядеть красиво, в соответствии с задуманным дизайном, а в старых (это относится к Internet Explorer версии 8 и ниже) они останутся с оформлением «по умолчанию», характерным для каждой конкретной операционной системы.

Фокус заключается в использовании псевдоселекторов :checked и :not. При этом сам чекбокс или радиокнопка делаются невидимыми, а их эмуляция осуществляется с помощью псевдоселекторов :before и :after для тега <label>, который, как мы знаем, переключает состояния элемента формы, если он привязан к нему через атрибут for.

В HTML-коде это выглядит следующим образом:

<input type="checkbox" class="checkbox" id="checkbox" />
<label for="checkbox">Я переключаю чекбокс</label>

<input type="radio" class="radio" id="radio" />
<label for="radio">А я переключаю радиокнопку</label>

При этом важно, чтобы тег <label> обязательно был расположен после тега <input>.

Далее в дело вступает CSS. В комментариях к коду для чекбокса я написал пояснения:

/* Cначала обозначаем стили для IE8 и более старых версий
т.е. здесь мы немного облагораживаем стандартный чекбокс. */
.checkbox {
	vertical-align: top;
	margin: 0 3px 0 0;
	width: 17px;
	height: 17px;
}
/* Это для всех браузеров, кроме совсем старых, которые не поддерживают
селекторы с плюсом. Показываем, что label кликабелен. */
.checkbox + label {
	cursor: pointer;
}

/* Далее идет оформление чекбокса в современных браузерах, а также IE9 и выше.
Благодаря тому, что старые браузеры не поддерживают селекторы :not и :checked,
в них все нижеследующие стили не сработают. */

/* Прячем оригинальный чекбокс. */
.checkbox:not(checked) {
	position: absolute;
	opacity: 0;
}
.checkbox:not(checked) + label {
	position: relative; /* будем позиционировать псевдочекбокс относительно label */
	padding: 0 0 0 60px; /* оставляем слева от label место под псевдочекбокс */
}
/* Оформление первой части чекбокса в выключенном состоянии (фон). */
.checkbox:not(checked) + label:before {
	content: '';
	position: absolute;
	top: -4px;
	left: 0;
	width: 50px;
	height: 26px;
	border-radius: 13px;
	background: #CDD1DA;
	box-shadow: inset 0 2px 3px rgba(0,0,0,.2);
}
/* Оформление второй части чекбокса в выключенном состоянии (переключатель). */
.checkbox:not(checked) + label:after {
	content: '';
	position: absolute;
	top: -2px;
	left: 2px;
	width: 22px;
	height: 22px;
	border-radius: 10px;
	background: #FFF;
	box-shadow: 0 2px 5px rgba(0,0,0,.3);
	transition: all .2s; /* анимация, чтобы чекбокс переключался плавно */
}
/* Меняем фон чекбокса, когда он включен. */
.checkbox:checked + label:before {
	background: #9FD468;
}
/* Сдвигаем переключатель чекбокса, когда он включен. */
.checkbox:checked + label:after {
	left: 26px;
}
/* Показываем получение фокуса. */
.checkbox:focus + label:before {
	box-shadow: 0 0 0 3px rgba(255,255,0,.5);
}

Для радиокнопки будет по сути то же самое:

.radio {
	vertical-align: top;
	width: 17px;
	height: 17px;
	margin: 0 3px 0 0;
}
.radio + label {
	cursor: pointer;
}
.radio:not(checked) {
	position: absolute;
	opacity: 0;
}
.radio:not(checked) + label {
	position: relative;
	padding: 0 0 0 35px;
}
.radio:not(checked) + label:before {
	content: '';
	position: absolute;
	top: -3px;
	left: 0;
	width: 22px;
	height: 22px;
	border: 1px solid #CDD1DA;
	border-radius: 50%;
	background: #FFF;
}
.radio:not(checked) + label:after {
	content: '';
	position: absolute;
	top: 1px;
	left: 4px;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: #9FD468;
	box-shadow: inset 0 1px 1px rgba(0,0,0,.5);
	opacity: 0;
	transition: all .2s;
}
.radio:checked + label:after {
	opacity: 1;
}
.radio:focus + label:before {
	box-shadow: 0 0 0 3px rgba(255,255,0,.5);
}

Вот таким несложным образом это и делается. Благодаря данному способу, оформить чекбоксы и радиокнопки с помощью CSS можно так, как вам будет угодно.

Комментарии (62)
  1. 1
    Сергей
    /* Показываем получение фокуса. */
    .checkbox:focus + label:before {
     box-shadow: 0 0 0 3px rgba(255,255,0,.5);
    }

    Не вижу, что тут происходит, что это за тень? Поясните пожалуйста!
    А за решение спасибо!

  2. 7
    Мой Хозяин

    Здравствуйте и все-таки как сделать для радио кнопки?

  3. 9
    Михаил

    Здравствуйте. Если обновить станицу, то все чекбоксы (выбранные) остаются в состание чекет. Что можно с эти сделать?

  4. 11
    RiA

    Здравствуйте, подскажите пожалуйста в чем может быть проблема?: стоит фильтр характеристик на сайте, при нажатии на любой фильтр — работает только самый верхний чекбокс (только самая первая характеристика — все остальные не подвижны)

  5. 12
    Роман

    Когда клацаю по чекбоксу, текст сползает постепенно вниз.

  6. 13
    Артем

    Ничего не работает в мозиле и в хроме пробовал не пашет как было так и осталось!

  7. 14
    Никита

    Всё прекрасно работает. Автору спасибо)

  8. 15
    PuNKeR

    Подскажите, а как сделать, чтобы label был с левой стороны?

  9. 16
    Дмитрий

    Спасибо, очень полезно

  10. 17
    Алексей

    Доброго времени суток!
    Спасибо за отличную статью.
    Небольшое дополнение: в хроме может не срабатывать стиль checkbox:checked + label:after
    Что бы исправить это нужно поместить чекбокс в div:
    checkbox

  11. 19

    Классная статья о таком способе я еще не знал

  12. 20
    xxxLOGIATxxx

    Слишком большая зависимость от тега label. Например в Drupal 8 эти два элемента периодически отображаются в таблицах, причём в разных столбцах, что делает этот код неюзабельным, поскольку ячейка таблицы останется пустой. Попробую Ваш js вариант. А статья хорошая и доходчивая.