Робимо забавні форми з допомогою Flexbox

30

Від автора: скажу чесно: в HTML формах мало чого забавного, але вони є невід’ємною частиною веб-розробки. І на щастя для нас, деякі усталені проблеми можна вирішити за допомогою CSS flexbox.

Давайте подивимося, як форми створюються без flexbox. Яку розмітку ви візьмете для таких полів?

Зазвичай ми використовуємо розмітку типу:

name
experience
HTML
CSS
JavaScript

Як тільки ви починаєте прописувати стилі, виникає ряд проблем:

Вихідний порядок лейблів і асоційованих з ними полів залежить від типу полів. Лейбл зазвичай розташовується перед полем форми, але з чекбоксами і радіокнопками його краще розміщувати після. Якщо ви зміните тип полів, вам потрібно змінювати їх порядок.

Досить складно однаково вирівняти і встановити однаковий розмір для полів input, textarea і select. У більшості таких полів є свої стилі за замовчуванням, які можуть несподівано змінюватися в окремих браузерах.

Тільки методом проб і помилок можна вирівняти лейбли з відповідними полями форми.

Якщо лейбл розташований перед полем форми, неможливо змінити його стилі, при активації поля або зміну стану контенту (на даний момент).

Flexbox вирішує ці проблеми. Ми можемо писати чистий і послідовний HTML-код, де лейбли будуть розташовані після полів, і нам не доведеться використовувати класи-хелпери.

Що таке Flexbox?

Flexbox – чарівний спосіб позиціонування декількох елементів на сторінці. Всі елементи можна вирівняти горизонтально, вертикально, відсортувати у звичайному і протилежному порядку, а також змінити їх розмір по відношенню до інших елементів. Flexbox досить заплутаний інструмент, і навіть після декількох місяців роботи з ним вам може знадобитися документація. Базовий код включення flexbox:

.container {
display: flex;
}

От і все. Всі дочірні елементи контейнера .container тепер є елементами flexbox, який вибудує їх за замовчуванням в один ряд.

Головна відмінність flexbox від систем сіток типу CSS Grid Module в тому, що flexbox працює в одному вимірі. Елементи flexbox вишиковуються в одну лінію і за необхідності обертаються в контейнери. В сітках використовуються колонки та рядки без контейнерів.

Flexbox слабкіше сіток, але він ідеально підходить для вибудовування дрібних компонентів типу меню, списків і полів форм.

Чому немає класів?

Люди, що працюють з SMACSS і BEM, можуть дивуватися відсутності класів в цій статті. HTML-код і CSS повинні бути чистими і понятими без зайвих відволікаючих факторів.

Код можна було б розглядати, як базові стилі для всіх форм на сайті, якщо на сайті використовується один макет. Класи додати можна, але вони необов’язкові для невеликих сайтів або демонстрацій.

Підключаємо flexbox до форми

Код зображення вище можна подивитися в цьому демо:

Подивіться на HTML код, і ви побачите, що теги label скрізь розташовані після полів форми, незважаючи на їх тип.

name
experience
HTML

Кожен div — flexbox контейнер, а властивість align-items: center вирівнює лейбли і поля по вертикалі:

fieldset div {
display: flex;
align-items: center;
}

Поля форми і лейбли тепер є flexbox елементами, але в більшості випадків вони розташовані в неправильному порядку. Лейбл повинен йти першим:

Так форма відображається в старих браузерах типу IE9 і нижче. Виправити це можна за допомогою властивості order, яке приймає позитивне або від’ємне число. Чим менше це число, тим раніше елемент відображається на сторінці:

label {
order: 1;
width: 10em;
padding-right: 0.5 em;
}
input, textarea, select {
order: 2;
flex: 1 1 auto;
}

Для ідеального вирівнювання лейблів ми використовували властивості width і padding. Один мінус flexbox – якщо текстові лейбли будуть довшими, доведеться вручну настроювати ширину.

Зверніть увагу на властивість flex: 1 1 auto, задане для полів input, textarea і select. Властивість flex – це скорочення, яке визначає, як елемент буде змінюватися в доступному йому просторі. Приймаються три значення:

flex-grow – простір, на яке елемент може вирости по відношенню до інших елементів. Наприклад, значення 2 говорить, що елемент буде в два рази ширше будь-якого елемента зі значенням 1.

flex-shrink – простір, на яке елемент може стиснутися.

flex-basis – початкова ширина флекс-елемента.

Властивість flex: 1 1 auto каже: «використовуй весь вільний простір». Поля форми використовують такі ж розміри, і немає потреби возитися з padding’ами b border’ами!

На жаль, тепер наші чекбокси мають неправильні стилі, але ми можемо прямо вказати стилі для чекбоксов і радіокнопок. Так, цього не було б, якщо б ми використовували класи! Код нижче поміщає ці поля перед лейблами, зупиняє, використовуючи весь простір, і застосовує зовнішній відступ margin, рівний ширині лейблу:

input[type=»checkbox»], input[type=»radio»] {
order: 1;
flex: none;
width: auto;
margin-left: 10em;
}

Ми також можемо знайти лейбли за допомогою родинних селекторів (~ чи +), так як вони йдуть відразу після полів форми. Можна відключити ширину за замовчуванням і поставити невеликий padding:

input[type=»checkbox»] ~ label, input[type=»radio»] ~ label {
width: auto;
padding-left: 0.4 em;
}

Додайте щіпку кольорів і стилів, і ми отримаємо гарну форму, яка буде відмінно виглядати з будь-якими полями.

Стилізація лейблів

Ще один плюс того, що лейбли йдуть після полів форми, в тому, що ми можемо їх стилізувати під стан полів. Наприклад, можна зробити лейбл червоним, коли поле отримує фокус:

input:focus ~ label, textarea:focus ~ label, select:focus ~ label {
color: #933;
}

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

input:checked ~ label {
font-weight: bold;
}

Парочка CSS переходів, і ви зможете змінювати розмір лейблів, рухати їх, плавно показувати і т. д.

Підтримка flexbox в браузерах

Flexbox підтримується у всіх сучасних браузерах. У IE11 є кілька проблем, але вони відносяться до більш складним властивостями, не тим, які ми використовували в нашій статті. В IE10 потрібний префікс –ms-, з ним все працює.

В старих браузерах всі поля відображаються перед лейблами, однак порядок вкладок залишається правильний. Все залежить від типу використовуваного поля.

Замішання викликають лише скрін рідери. Проблеми можуть виникнути в тому випадку, якщо скрін рідер буде покладатися на вихідний порядок розташування елементів в HTML, а не на лейбли. Я не чув про якісь інші проблеми зі скрін рідерами. Дайте мені знати, якщо ви стикалися з чим-небудь!

Якщо ця стаття спонукала вас використовувати flexbox на всіх формах, майте на увазі, що властивість display: flex не можна застосувати до елементів
з-за помилок у Chrome і Firefox. Сподіваюся, мої поради заощадили вас пару годин, які мені довелося витратити!