🕐 7 хв читання

Верстка форм

Конспект лекції: елементи форм, стилізація полів, валідація, label, outline, стани :focus та :hover

Навіщо потрібні форми?

Форми — спосіб отримати дані від користувача: ім'я, email, повідомлення, вибір опцій тощо.

  • Текстові поля<input> (однорядкове), <textarea> (багаторядкове).
  • Чекбокси — вибір кількох варіантів зі списку.
  • Радіокнопки — вибір одного варіанту зі списку.
  • Випадаючі списки<select>.
  • Кнопки — відправлення, скидання, дія.

Тег <input> — однорядкове поле

<input> — самозакривний тег. Тип визначається атрибутом type:

Тип Призначення
text (за замовчуванням) Звичайне текстове поле
password Пароль (символи приховані)
email Email (вбудована перевірка на @)
search Пошук (має кнопку очищення ×)
number Число (стрілки ↑↓, атрибути min, max, step)
date Дата (календар браузера)
time Час
datetime-local Дата + час
range Повзунок
color Вибір кольору
Якщо type не вказано — це text. Довідник усіх типів: MDN — <input>.

Атрибути input

Атрибут Призначення
placeholder Підказка всередині поля (зникає при введенні)
value Значення за замовчуванням (як ніби користувач вже ввів)
name Ім'я поля для відправлення на сервер
required Поле обов'язкове (форма не відправиться без нього)
disabled Поле заблоковане (не можна редагувати)
id Унікальний ідентифікатор (для зв'язку з <label>)
autocomplete Підказка браузеру, що автозаповнювати ("name", "email", "tel"…)

autocomplete — автозаповнення браузером

Атрибут autocomplete підказує браузеру, яку збережену інформацію підставити в поле:

<input type="text" name="fullname" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
Правильний autocomplete покращує UX: браузер пропонує збережені дані в один клік. Особливо важливо на мобільних пристроях.
placeholder — це приклад очікуваного значення (наприклад, «Іван Петренко»).
<label> або підказка — це назва поля (наприклад, «Ваше ім'я»).

Стилізація input

<input> можна стилізувати як будь-який блочний елемент:

.field {
    width: 100%;
    padding: 10px 15px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 16px;
    box-sizing: border-box;
    background-color: #fff;
    color: #333;
}
Завжди додавайте box-sizing: border-box для полів форми — інакше padding збільшить загальну ширину елемента.

accent-color — стилізація чекбоксів та радіокнопок

Раніше змінити колір чекбокса або радіокнопки було неможливо без хаків. Сучасна властивість accent-color вирішує це одним рядком:

/* Усі інтерактивні елементи — в кольорах бренду */
input[type="checkbox"],
input[type="radio"],
input[type="range"] {
    accent-color: #e53935;
}
accent-color підтримується усіма сучасними браузерами з 2022 року. Працює для checkbox, radio, range та progress.

Тег <textarea> — багаторядкове поле

  • На відміну від <input>, має закривний тег: <textarea>...</textarea>.
  • Текст між тегами — значення за замовчуванням.
  • Користувач може змінювати розмір (перетягування кутка).

Обмеження розміру

textarea.field {
    min-width: 250px;
    max-width: 100%;
    min-height: 100px;
    max-height: 300px;
    font-family: inherit;  /* без цього — моноширинний шрифт! */
}
<textarea> за замовчуванням має моноширинний шрифт (monospace). Задайте font-family: inherit, щоб успадкувати шрифт від батька.
Задайте однакові min-width і max-width, щоб заборонити горизонтальну зміну розміру. Аналогічно для висоти.

Кнопки <button>

Три типи кнопок:

Тип Поведінка
submit Відправляє форму (потрібен тег <form>)
reset Скидає всі поля до значень за замовчуванням
button Нічого не робить (для JavaScript-обробників)

Стилізація кнопки

.button {
    padding: 12px 24px;
    border: none;
    background-color: #e53935;
    color: #fff;
    font-size: 16px;
    font-family: inherit;
    cursor: pointer;  /* лапка при наведенні */
    border-radius: 4px;
}
Кнопки виглядають по-різному в різних браузерах. Завжди скидайте border, background, font-family і стилізуйте з нуля.
Додавайте cursor: pointer — за замовчуванням на кнопках курсор-стрілка, а не лапка.

Тег <label> — підпис поля

<label> — семантичний елемент, що зв'язує текст підпису з полем введення.

Два способи зв'язування

1. Обгортка — input всередині label:

<label>
    <span class="hint">Ваше ім'я</span>
    <input type="text" class="field">
</label>

2. Атрибут for + id — label окремо від input:

<label for="user-email">Email</label>
<input type="email" id="user-email" class="field">
Клік на <label> автоматично ставить фокус на пов'язаний input. Це зручно для UX і важливо для доступності (скрінрідери).

Тег <form>

<form> об'єднує поля в єдину форму. Без нього кнопка submit не працюватиме.

<form action="/api/contact" method="POST">
    <label>
        <span class="hint">Ім'я</span>
        <input type="text" name="username" required>
    </label>
    <button type="submit">Надіслати</button>
</form>
Атрибут Призначення
action URL, куди відправляються дані
method HTTP-метод: GET або POST
<form> — не просто семантичний тег. Він має практичне значення: об'єднує поля, додає подію submit, дозволяє кнопці type="submit" працювати.

Валідація полів

HTML має вбудовані валідатори — перевірки перед відправленням форми:

Спосіб Що перевіряє
required Поле не порожнє
type="email" Наявність символу @
min / max Діапазон числового значення
minlength / maxlength Мінімальна / максимальна кількість символів
pattern Перевірка за регулярним виразом
Порядок перевірки: спочатку required (чи не порожнє), потім type (формат), потім pattern та інші обмеження.
Вбудована валідація — лише базовий захист. Для серйозних проєктів потрібна додаткова перевірка на сервері (backend).

Стани :focus та :hover

:focus — поле у фокусі

Коли користувач клікнув на поле або перейшов клавішею Tab:

.field:focus {
    outline: 2px solid #1976d2;
    outline-offset: 2px;
}

:focus-visible — фокус тільки з клавіатури

Проблема :focus: outline з'являється і при кліку мишею, що дратує дизайнерів. Рішення — :focus-visible:

/* Прибираємо outline при кліку мишею */
.field:focus {
    outline: none;
}

/* Показуємо outline тільки при навігації клавіатурою */
.field:focus-visible {
    outline: 2px solid #1976d2;
    outline-offset: 2px;
}
:focus-visible підтримується усіма сучасними браузерами з 2022 року. Це стандартний підхід: красиво для миші, доступно для клавіатури.

:hover — наведення мишею

.field:hover {
    border-color: #666;
}
Ніколи не прибирайте outline для клавіатурного фокусу — це критично для доступності. Використовуйте :focus-visible, щоб outline з'являвся лише при навігації клавіатурою, а не при кліку мишею.

Властивість outline

outline — обведення навколо елемента, яке не впливає на розміри та розкладку.

Властивість Що задає
outline-width Товщина обведення
outline-style solid, dotted, dashed, none
outline-color Колір обведення
outline-offset Відстань від межі елемента до обведення
outline Скорочення: width style color
outline не входить до блочної моделі — навіть із border-box він не змінює розмір елемента. Це ключова відмінність від border.

Групування селекторів

Якщо кілька елементів мають однакові стилі, їх селектори можна перелічити через кому:

/* Замість дублювання: */
.field:focus,
.button:focus {
    outline: 2px solid #1976d2;
    outline-offset: 2px;
}

/* Однакові шрифти для заголовків: */
h1,
h2,
h3 {
    font-family: "Segoe UI", sans-serif;
}

Структура форми: повний приклад

<form class="contact-form" action="/api/contact" method="POST">
    <div class="form-row">
        <label class="form-group">
            <span class="form-hint">Ваше ім'я</span>
            <input type="text" class="field"
                   name="username" placeholder="Іван Петренко" required>
        </label>
    </div>

    <div class="form-row">
        <label class="form-group">
            <span class="form-hint">Email</span>
            <input type="email" class="field"
                   name="email" placeholder="name@example.com" required>
        </label>
    </div>

    <div class="form-row">
        <label class="form-group">
            <span class="form-hint">Повідомлення</span>
            <textarea class="field"
                      name="message" placeholder="Ваше повідомлення..." required></textarea>
        </label>
    </div>

    <div class="form-row">
        <button type="submit" class="button">Надіслати</button>
    </div>
</form>
/* CSS для відступів між рядками форми */
.form-row:nth-child(n+2) {
    margin-top: 20px;
}

.form-hint {
    display: block;
    margin-bottom: 6px;
    font-weight: 600;
}

Налагодження станів у DevTools

У DevTools (інспекторі браузера) є панель :hov, яка дозволяє емулювати псевдостани:

  1. Виділіть елемент у вкладці Elements.
  2. Натисніть кнопку :hov (у панелі Styles).
  3. Увімкніть :focus, :hover, :active тощо.
  4. Стилі цього стану стануть видимими та редагованими.
Можна одночасно увімкнути кілька станів (наприклад, :hover + :focus), щоб побачити, який стиль перекриває інший.

Підсумок

Тема Ключове
<input> Однорядкове поле; type визначає тип (text, email, number…)
<textarea> Багаторядкове поле; font-family: inherit; обмежити розмір
<button> submit (відправити), reset (скинути), button (JS)
<label> Підпис поля; клік → фокус; зв'язок через обгортку або for+id
<form> Об'єднує поля; action + method; подія submit
placeholder Приклад значення (не замінює label!)
required Обов'язкове поле (вбудована валідація)
outline Обведення при фокусі; не впливає на розміри; не видаляйте!
:focus / :hover Стани для інтерактивних елементів; відлагоджувати через :hov у DevTools
cursor: pointer Лапка на кнопках (за замовчуванням — стрілка)
:focus-visible Outline тільки при навігації клавіатурою (не при кліку мишею)
accent-color Колір checkbox, radio, range — одним рядком CSS
autocomplete Підказка браузеру для автозаповнення ("name", "email", "tel")
🔍
Почніть вводити назву лекції або тему