Стилізація input checkbox

Опублікував(а): Масальська Анастасія
Оновлено: 15.03.2024

Ця стаття «Стилізація input checkbox» розкриває тему про використання та стилізацію елементів checkbox (чекбоксів). При створенні розмітки для сайту розробники часто стикаються з необхідністю стилізації чекбоксів, іноді вони використовуються не в тих контекстах. Давайте ближче познайомимося з цим елементом.

Користувальницькі вхідні дані форми з сучасними функціями CSS

Стилізація input checkbox
Стилізація input checkbox

В сучасних умовах існує можливість створювати власні прапорці, перемикачі та тумблери, зберігаючи при цьому семантику та доступність. І при цьому нам не потрібно використовувати JavaScript або додавати додаткові HTML-елементи! Слід зазначити, що це стало набагато простіше, ніж раніше.

Причина полягає в тому, що тепер ми маємо можливість стилізувати псевдоелементи ::before і самі теги. Це дозволяє нам зберігати та стилізувати елемент input, і нам не потрібні додаткові HTML-елементи. Раніше нам доводилося покладатися на додаткові функції або використовувати :: after для створення індивідуального дизайну.

Покрокові дії з використанням HTML

Розглянемо HTML-код.

Тут нема нічого складного. Ми можемо стилізувати наші input-елементи, використовуючи тільки цей HTML:

<!-- Checkbox -->
<input type="checkbox">

<!-- Radio -->
<input type="radio">

<!-- Switch -->
<input type="checkbox" class="switch">

Це все, що стосується HTML-частини. Однак рекомендуємо додати атрибути name та id, а також відповідний елемент :

<!-- Checkbox -->
<input type="checkbox" name="c1" id="c1">
<label for="c1">Checkbox</label>

<!-- Radio -->
<input type="radio" name="r1" id="r1">
<label for="r1">Radio</label>

<!-- Switch -->
<input type="checkbox" class="switch" name="s1" id="s1">
<label for="s1">Switch</label>

Переходимо до стилю.

Насамперед ми перевіряємо підтримку якості appearance: none;, включаючи його префіксні варіанти. Ця властивість appearance є ключовою, оскільки вона призначена для видалення стилів браузера за замовчуванням елемента. У разі відсутності підтримки цієї властивості, стилі не будуть застосовані, і елемент відображатиметься з браузерними стилями введення за замовчуванням. Це цілком нормально і є прикладом прогресивного поліпшення дії.

@supports(-webkit-appearance: none) or (-moz-appearance: none) {
  input[type='checkbox'],
  input[type='radio'] {
    -webkit-appearance: none;
    -moz-appearance: none;
  }
}

У поточній конфігурації дизайн – це готовий проєкт, але як забезпечується його підтримка:

Як і у випадку з посиланнями, важливо врахувати різні інтерактивні стани елементів форми при їх стилізації:

Наприклад, так можна стилізувати перемикач, створити ручку та врахувати стан :check

.switch {
  width: 38px;
  border-radius: 11px;
}

/* The toggle knob */
.switch::after {
  left: 2px;
  top: 2px;
  border-radius: 50%;
  width: 15px;
  height: 15px;
  background: var(--ab, var(--border));
  transform: translateX(var(--x, 0));
}

/* Change color and position when checked */
.switch:checked {
  --ab: var(--active-inner);
  --x: 17px;
}

/* Drop the opacity of the toggle knob when the input is disabled */
.switch:disabled:not(:checked)::after {
  opacity: .6;
}

Ми використовуємо елемент як контейнер. Ручка всередині входу створюється з допомогою псевдоелемента ::after. Тепер немає потреби у додатковій розмітці!

При перегляді стилів у демо-версії можна помітити, що ми визначаємо деякі властивості користувача CSS. Це стає зручним способом управління повторно використовуваними значеннями таблиці стилів.

@supports(-webkit-appearance: none) or (-moz-appearance: none) {
  input[type='checkbox'],
  input[type='radio'] {
    --active: #275EFE;
    --active-inner: #fff;
    --focus: 2px rgba(39, 94, 254, .25);
    --border: #BBC1E1;
    --border-hover: #275EFE;
    --background: #fff;
    --disabled: #F6F8FF;
    --disabled-inner: #E1E6F9;
  }
}

Однак є ще одна причина використовувати власні властивості – вони відмінно підходять для оновлення значень залежно від стану елемента! Без заглиблення в деталі, ось приклад того, як ми можемо використовувати власні властивості для різних станів.

input[type='checkbox'],
input[type='radio'] {
  --active: #275EFE;
  --border: #BBC1E1;
  border: 1px solid var(--bc, var(--border));
}

/* Override defaults */
input[type='checkbox']:checked,
input[type='radio']:checked {
  --b: var(--active);
  --bc: var(--active);
}
  
/* Apply another border color on hover if not checked & not disabled */
input[type='checkbox']:not(:checked):not(:disabled):hover,
input[type='radio']:not(:checked):not(:disabled):hover {
  --bc: var(--border-hover);
}

Для забезпечення доступності ми додаємо власні стилі для стану фокусу. Прибираємо контур за замовчуванням, оскільки його не можна округлити, як інші елементи, які ми стилізуємо. Однак за допомогою border-radius та box-shadow ми можемо створити закруглений стиль, аналогічний контуру.

input[type='checkbox'],
input[type='radio'] {
  --focus: 2px rgba(39, 94, 254, .25);
  outline: none;
  transition: box-shadow .2s;
}

input[type='checkbox']:focus,
input[type='radio']:focus {
  box-shadow: 0 0 0 var(--focus);
}

Також можна вирівняти та стилізувати елемент , що йде відразу після елемента у HTML:

<input type="checkbox" name="c1" id="c1">
<label for="c1">Checkbox</label>
input[type='checkbox'] + label,
input[type='radio'] + label {
  display: inline-block;
  vertical-align: top;
  /* Additional styling */
}

input[type='checkbox']:disabled + label,
input[type='radio']:disabled + label {
    cursor: not-allowed;
}

Коди стилізації input checkbox з HTML

<ul>
  <li>
    <input id="c1" type="checkbox">
    <label for="c1">Checkbox</label>
  </li>
  <li>
    <input id="c2" type="checkbox" checked>
    <label for="c2">Checkbox</label>
  </li>
  <li>
    <input id="r1" type="radio" name="radio" value="1">
    <label for="r1">Radio</label>
  </li>
  <li>
    <input id="r2" type="radio" name="radio" value="2" checked>
    <label for="r2">Radio</label>
  </li>
  <li>
    <input id="s1" type="checkbox" class="switch">
    <label for="s1">Switch</label>
  </li>
  <li>
    <input id="s2" type="checkbox" class="switch" checked>
    <label for="s2">Switch</label>
  </li>
</ul>

<ul>
  <li>
    <input id="c1d" type="checkbox" disabled>
    <label for="c1d">Checkbox</label>
  </li>
  <li>
    <input id="c2d" type="checkbox" checked disabled>
    <label for="c2d">Checkbox</label>
  </li>
  <li>
    <input id="r1d" type="radio" name="radiod" value="1" disabled>
    <label for="r1d">Radio</label>
  </li>
  <li>
    <input id="r2d" type="radio" name="radiod" value="2" checked disabled>
    <label for="r2d">Radio</label>
  </li>
  <li>
    <input id="s1d" type="checkbox" class="switch" disabled>
    <label for="s1d">Switch</label>
  </li>
  <li>
    <input id="s2d" type="checkbox" class="switch" checked disabled>
    <label for="s2d">Switch</label>
  </li>
</ul>

Коди стилізації input checkbox із CSS

@supports (-webkit-appearance: none) or (-moz-appearance: none) {
input[type='checkbox'], input[type='radio'] {
	--active: #275efe;
	--active-inner: #fff;
	--focus: 2px rgba(39, 94, 254, .3);
	--border: #bbc1e1;
	--border-hover: #275efe;
	--background: #fff;
	--disabled: #f6f8ff;
	--disabled-inner: #e1e6f9;
	-webkit-appearance: none;
	-moz-appearance: none;
	height: 21px;
	outline: none;
	display: inline-block;
	vertical-align: top;
	position: relative;
	margin: 0;
	cursor: pointer;
	border: 1px solid var(--bc, var(--border));
	background: var(--b, var(--background));
	transition: background 0.3s, border-color 0.3s, box-shadow 0.2s;
}
input[type='checkbox']:after, input[type='radio']:after {
	content: '';
	display: block;
	left: 0;
	top: 0;
	position: absolute;
	transition: transform var(--d-t, 0.3s) var(--d-t-e, ease), opacity var(--d-o, 0.2s);
}
input[type='checkbox']:checked, input[type='radio']:checked {
	--b: var(--active);
	--bc: var(--active);
	--d-o: 0.3s;
	--d-t: 0.6s;
	--d-t-e: cubic-bezier(0.2, 0.85, 0.32, 1.2);
}
input[type='checkbox']:disabled, input[type='radio']:disabled {
	--b: var(--disabled);
	cursor: not-allowed;
	opacity: 0.9;
}
input[type='checkbox']:disabled:checked, input[type='radio']:disabled:checked {
	--b: var(--disabled-inner);
	--bc: var(--border);
}
input[type='checkbox']:disabled + label, input[type='radio']:disabled + label {
	cursor: not-allowed;
}
input[type='checkbox']:hover:not(:checked):not(:disabled), input[type='radio']:hover:not(:checked):not(:disabled) {
	--bc: var(--border-hover);
}
input[type='checkbox']:focus, input[type='radio']:focus {
	box-shadow: 0 0 0 var(--focus);
}
input[type='checkbox']:not(.switch), input[type='radio']:not(.switch) {
	width: 21px;
}
input[type='checkbox']:not(.switch):after, input[type='radio']:not(.switch):after {
	opacity: var(--o, 0);
}
input[type='checkbox']:not(.switch):checked, input[type='radio']:not(.switch):checked {
	--o: 1;
}
input[type='checkbox'] + label, input[type='radio'] + label {
	font-size: 14px;
	line-height: 21px;
	display: inline-block;
	vertical-align: top;
	cursor: pointer;
	margin-left: 4px;
}
input[type='checkbox']:not(.switch) {
	border-radius: 7px;
}
input[type='checkbox']:not(.switch):after {
	width: 5px;
	height: 9px;
	border: 2px solid var(--active-inner);
	border-top: 0;
	border-left: 0;
	left: 7px;
	top: 4px;
	transform: rotate(var(--r, 20deg));
}
input[type='checkbox']:not(.switch):checked {
	--r: 43deg;
}
input[type='checkbox'].switch {
	width: 38px;
	border-radius: 11px;
}
input[type='checkbox'].switch:after {
	left: 2px;
	top: 2px;
	border-radius: 50%;
	width: 15px;
	height: 15px;
	background: var(--ab, var(--border));
	transform: translateX(var(--x, 0));
}
input[type='checkbox'].switch:checked {
	--ab: var(--active-inner);
	--x: 17px;
}
input[type='checkbox'].switch:disabled:not(:checked):after {
	opacity: 0.6;
}
input[type='radio'] {
	border-radius: 50%;
}
input[type='radio']:after {
	width: 19px;
	height: 19px;
	border-radius: 50%;
	background: var(--active-inner);
	opacity: 0;
	transform: scale(var(--s, 0.7));
}
input[type='radio']:checked {
	--s: 0.5;
}
}
ul {
	margin: 12px;
	padding: 0;
	list-style: none;
	width: 100%;
	max-width: 320px;
}
ul li {
	margin: 16px 0;
	position: relative;
}
html {
	box-sizing: border-box;
}
* {
	box-sizing: inherit;
}
*:before, *:after {
	box-sizing: inherit;
}
body {
	min-height: 100vh;
	font-family: 'Inter', Arial, sans-serif;
	color: #8a91b4;
	display: flex;
	justify-content: center;
	align-items: center;
	background: #f6f8ff;
}
@media (max-width: 800px) {
	body {
		padding: 20px;
}
}

Презентація стилізації:

Сьогодні приємно створювати індивідуальні стилі для форм, оскільки це вимагає менше розмітки завдяки псевдоелементам, які знаходяться прямо всередині елементів введення. Налаштовуються властивості полегшують зміну стилів. Браузери добре підтримують цей досвід розробки завдяки @supports. Загалом, це зручніший процес, ніж раніше!