Нестандартні елементи форм
Конспект лекції: display: inline-block, випадаючий список <select>, background-властивості, радіокнопки, чекбокси, кастомна стилізація, псевдоелементи, селектори + і ~
display: inline-block
Окрім block, inline та flex, є ще одне значення —
inline-block. Воно поєднує поведінку строкових і блочних елементів.
Що від чого?
| Від строкових (inline) | Від блочних (block) |
|---|---|
| Елементи розташовуються в рядок | Можна задавати width і height |
Без width ширина визначається вмістом |
padding, margin працюють повноцінно |
Позиціонуються через text-align |
Не розбиваються на частини при переносі рядка |
<button> за замовчуванням має display: inline-block. Тому її можна
центрувати через text-align: center на батьківському елементі.
Центрування кнопки
.form-row:last-child {
text-align: center; /* кнопка всередині стане по центру */
}
Пробіл між inline-block елементами
Між inline-block елементами з'являється пробіл (~4px). Він не «створюється» — він бере початок
від символу переносу рядка або пробілу у вашому HTML-коді.
Як виникає?
<!-- Між цими div є перенос рядка → браузер показує 1 пробіл -->
<div class="card">...</div>
<div class="card">...</div>
Як прибрати?
| Спосіб | Недолік |
|---|---|
| Писати теги без пробілів між ними | Крихке рішення — будь-який пробіл зламає верстку |
font-size: 0 на батьку, відновити на дітях |
Ламає відносні одиниці (em), незручно |
| Flexbox замість inline-block | Найкраще рішення — без хаків |
display:
flex замість inline-block. Flex-елементи не мають пробілів між собою.
Випадаючий список: <select> + <option>
<select> — елемент форми для вибору одного варіанту зі списку. <option>
— кожен варіант вибору (може бути лише всередині <select>).
<label>
<span class="form-hint">Оберіть місто</span>
<select class="select" name="city">
<option>Київ</option>
<option selected>Львів</option>
<option>Одеса</option>
<option>Харків</option>
</select>
</label>
| Атрибут | Призначення |
|---|---|
selected |
Позначає варіант, вибраний за замовчуванням |
multiple |
Дозволяє обрати кілька (рідко використовується — незручний UX) |
selected — вибраним стає перший <option>. Якщо selected
є на кількох — виграє останній у коді.
Коли select, а коли radio?
- Варіантів більше 5
- Займає мінімум місця
- Потрібно 2 кліки (відкрити + обрати)
- Варіантів 2–5
- Усі варіанти видимі одразу
- Вибір за 1 клік
appearance: none — скидання стилізації
Браузери мають власну стилізацію для елементів форм (<select>, деякі типи <input>),
яку складно перевизначити. Властивість appearance зі значенням none вимикає цю
базову стилізацію.
.select {
-webkit-appearance: none; /* Safari, старі Chrome */
-moz-appearance: none; /* Firefox */
appearance: none; /* стандарт */
}
appearance:
none без префіксів. Але для повної сумісності додавайте всі три рядки.
Де застосовувати?
<select>— прибирає стандартну стрілку, дозволяє повну стилізаціюinput[type="search"]— прибирає нестандартне оформлення в Safari
appearance: none повсюдно. Кнопки та звичайні <input>
прекрасно стилізуються і без нього.
background — фон елемента
Група властивостей для керування фоном: колір, зображення, повторення, позиція, розмір.
background-color
Задає колір фону. Рекомендується завжди підкладати колір під background-image — на випадок, якщо
картинка не завантажиться.
background-image
background-image: url("icons/arrow.svg");
Завантажує зображення і показує його як фон елемента. Без додаткових налаштувань — повторюється і заповнює весь блок.
background-repeat
| Значення | Поведінка |
|---|---|
repeat (за замовчуванням) |
Повторюється по горизонталі та вертикалі |
repeat-x |
Тільки по горизонталі |
repeat-y |
Тільки по вертикалі |
no-repeat |
Без повторення (одна копія) |
no-repeat використовується найчастіше — для іконок, декоративних елементів,
унікальних фонових зображень.
background-position
Визначає положення фонового зображення. Два значення: горизонталь і вертикаль.
/* 9 опорних точок */
background-position: left top; /* лівий верхній кут */
background-position: center center; /* строго по центру */
background-position: right center; /* справа по центру */
/* Зі зміщенням від опорної точки */
background-position: right 10px center; /* справа, -10px ліворуч */
right
center зі зміщенням ліворуч.
background-size
| Значення | Поведінка |
|---|---|
200px auto |
Ширина 200px, висота — пропорційно |
auto 100px |
Висота 100px, ширина — пропорційно |
cover |
Покриває весь блок (частина картинки може бути обрізана) |
contain |
Вписується в блок цілком (частина блоку може бути порожньою) |
contain — для зображень, де важливо показати все (портрети, діаграми).
Стилізація <select>: повний приклад
Після скидання appearance: none елемент <select> стає звичайним
прямокутником. Тепер ми додаємо власну стрілку через background-image:
.select {
display: block;
width: 100%;
padding: 10px 35px 10px 15px; /* більше padding-right для стрілки */
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
font-family: inherit;
box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: url("icons/arrow-down.svg");
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 12px auto;
}
<select> у <label> — щоб клік по
підпису активував поле. І додайте стилі :focus однакові з іншими полями.
Радіокнопки: input type="radio"
Радіокнопки дозволяють обрати один варіант із групи. Назва «radio» походить від старих радіоприймачів: натискаєш одну кнопку — інша вистрибує.
<label>
<input type="radio" name="gender" class="radio">
<span class="radio-text">Чоловіча</span>
</label>
<label>
<input type="radio" name="gender" class="radio">
<span class="radio-text">Жіноча</span>
</label>
Атрибут name — створення радіогрупи
Без name кожна радіокнопка працює незалежно — можна обрати усі одночасно. Атрибут
name зв'язує радіокнопки в групу: у групі обрана лише одна.
name повинно відображати призначення групи: "gender",
"subscription", "delivery" — а не абстрактне "radiogroup".
<label> — тоді клік по тексту теж активує вибір.
Плюс <label> — строковий елемент, тому радіокнопки автоматично стоятимуть в одному рядку.
Псевдоелементи ::before та ::after (практика)
Псевдоелементи дозволяють додати до будь-якого елемента віртуальні блоки — без зміни HTML-коду. Вони створюються виключно через CSS.
Обов'язкова властивість content
.heading::before {
content: ""; /* обов'язково! без content — елемент не з'явиться */
display: block;
width: 60px;
height: 4px;
background-color: #4caf50;
margin-bottom: 10px;
}
Обмеження
Псевдоелементи не працюють для тегів:
<input>— самозакривний, без вмісту<textarea><select><img>— самозакривний
Пріоритет шарів
::before з'являється перед вмістом і має нижчий пріоритет (вміст його перекриває).
::after з'являється після вмісту і має вищий пріоритет (може перекрити вміст).
vertical-align — вирівнювання по вертикалі
Працює для inline та inline-block елементів. Визначає, як елемент вирівнюється
відносно рядка.
| Значення | Поведінка |
|---|---|
baseline (за замовчуванням) |
По базовій лінії тексту (нижній край букв) |
top |
По верхньому краю рядка |
middle |
По центру рядка |
bottom |
По нижньому краю рядка |
vertical-align: middle ідеально підходить для вирівнювання іконок, радіокнопок,
чекбоксів поряд із текстом.
Селектори + (суміжний) та ~ (загальний братський)
Ці селектори працюють між «братами» — елементами одного рівня вкладеності (один батько). Аналог селекторів
> (дитина) та пробілу (нащадок), але по горизонталі.
Селектор + (суміжний)
Стилізує елемент, якщо його безпосередній старший брат відповідає умові:
/* Стилізуємо .radio-text, якщо безпосередньо перед ним — .form-hint */
.form-hint + .radio-text {
color: red;
}
Селектор ~ (загальний братський)
Стилізує елемент, якщо будь-який його старший брат відповідає умові:
/* Стилізуємо .radio-text, якщо десь вище по коду є .form-hint */
.form-hint ~ .radio-text {
color: red;
}
Порівняння усіх чотирьох «горизонтально-вертикальних» селекторів
| Селектор | Напрямок | Строгість |
|---|---|---|
A B (пробіл) |
Батько → нащадок (будь-якої глибини) | М'який |
A > B |
Батько → безпосередня дитина | Строгий |
A ~ B |
Старший брат → будь-який молодший | М'який |
A + B |
Старший брат → безпосередній наступний | Строгий |
~ надійніший за +: якщо хтось вставить додатковий елемент
між братами, + зламається, а ~ — ні.
Кастомна стилізація радіокнопок
Стандартні радіокнопки не стилізуються: браузери не дозволяють змінювати колір, розмір, форму. Рішення — створити муляж і приховати оригінал.
Крок 1: створюємо муляж через ::before
Оскільки <input> не підтримує псевдоелементи, створюємо їх на сусідньому <span>:
.radio-text::before {
content: "";
display: inline-block;
width: 20px;
height: 20px;
margin-right: 8px;
vertical-align: middle;
background-image: url("icons/radio.svg");
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
Крок 2: передаємо стан :checked через селектор ~
/* Якщо радіокнопка обрана → підмінюємо картинку на муляжі */
.radio:checked ~ .radio-text::before {
background-image: url("icons/radio-active.svg");
}
::before елемента .radio-text,
якщо десь перед ним є .radio у стані :checked.
Крок 3: ховаємо оригінал доступно
.radio {
position: absolute;
width: 1px;
height: 1px;
clip-path: inset(50%);
overflow: hidden;
}
display: none або visibility: hidden — елемент
стане недоступним для скрінрідерів та клавіатурної навігації. clip-path: inset(50%) ховає
візуально, але зберігає доступність.
Крок 4: стан фокусу
/* Фокус з радіокнопки → візуальне виділення тексту */
.radio:focus ~ .radio-text {
outline: 2px solid #1976d2;
outline-offset: 2px;
}
position: absolute — коротко
position: absolute вириває елемент з нормального потоку документа і розміщує на окремому «шарі»:
- Інші елементи поводяться так, ніби абсолютного елемента не існує
- Ширина і висота розраховуються за вмістом (як у inline-block)
- Можна задавати
width,height— працюватимуть - Батьківський елемент не враховує висоту абсолютного нащадка
position (static, relative, absolute, fixed, sticky) розглядається у
наступних лекціях. Тут він потрібен лише для коректного приховування оригінальних radio/checkbox.
clip-path: inset() — візуальне обрізання
Властивість clip-path дозволяє показати тільки частину елемента, а решту — приховати.
/* Обрізати 50% з кожного боку — елемент зникає візуально */
clip-path: inset(50%);
/* Обрізати у формі кола */
clip-path: circle(50%);
/* Обрізати у формі багатокутника */
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
inset(50%) — обрізає 50% з кожного боку елемента. Область, що залишається = нічого. Візуально
елемент зникає, але залишається доступним для скрінрідерів.
clip: rect() робила те саме, але працювала лише з position:
absolute і є deprecated. Використовуйте clip-path — вона сучасніша і підтримує
більше форм обрізання.
Чекбокс: input type="checkbox"
Чекбокс — елемент «так/ні»: погодитися чи не погодитися. По суті — дві радіокнопки в одному елементі.
<label>
<input type="checkbox" name="consent" class="checkbox" required>
<span class="checkbox-text">Погоджуюсь на обробку персональних даних</span>
</label>
Стилізація абсолютно ідентична радіокнопкам:
- Створити муляж через
::beforeна.checkbox-text - Передати стан
:checkedчерез.checkbox:checked ~ .checkbox-text::before - Приховати оригінал через
position: absolute+clip - Додати стан
:focus
/* Ховаємо разом з radio — через запятую */
.radio,
.checkbox {
position: absolute;
width: 1px;
height: 1px;
clip-path: inset(50%);
overflow: hidden;
}
Сучасна альтернатива: accent-color
У файлі 06 ми вже згадували accent-color — властивість, яка дозволяє змінити колір стандартних
checkbox, radio, range без кастомної стилізації:
input[type="radio"],
input[type="checkbox"] {
accent-color: #e53935;
}
- Один рядок CSS
- Зберігає стандартну поведінку
- 100% доступність
- Обмежений контроль (лише колір)
- Повний контроль вигляду
- Дизайнер вирішує форму, анімацію
- Потрібен складний CSS
- Потрібно дбати про доступність
accent-color. Якщо потрібна
повна кастомізація — техніка з муляжем і ::before.
Підсумок
| Тема | Ключове |
|---|---|
display: inline-block |
Рядок + розміри; центрування через text-align; пробіл між елементами |
<select> + <option> |
Випадаючий список; selected — передвибраний; > 5 варіантів |
appearance: none |
Скидає стандартну стилізацію браузера для елементів форм |
background |
image + repeat + position + size; cover vs contain |
input type="radio" |
Вибір одного із групи; name зв'язує в радіогрупу |
::before / ::after |
Декоративні блоки через CSS; обов'язковий content; не для input/img |
vertical-align |
Вирівнювання inline/inline-block по вертикалі; middle для іконок |
Селектори + та ~ |
Братські селектори; + строгий, ~ м'який; тільки від старшого до молодшого
|
| Кастомна стилізація radio/checkbox | Муляж через ::before + стан :checked через ~ + доступне
приховування
|
position: absolute |
Вириває елемент з потоку; потрібний для clip |
clip-path: inset() |
Візуальне приховування зі збереженням доступності; замінює застарілу clip: rect() |
accent-color |
Сучасна альтернатива: змінити колір radio/checkbox одним рядком |