Стилизация текстовых полей формы
В этой статье рассмотрим различные варианты стилизации текстовых полей HTML-форм. Сначала создадим базовый вариант оформления input, а затем множество других, дополняя каждый из них небольшим количеством CSS.
Введение
Веб-формы являются неотъемлемой частью многих веб-сайтов. Они позволяют пользователю ввести те или иные данные, которые затем отправляются на сервер или обрабатываются на стороне клиента, например, для изменения интерфейса.
Веб-формы также часто называют HTML-формами . Их проектирование осуществляется с помощью элементов управления форм (текстовых полей, выпадающих списков, кнопок, чекбоксов и т.д.) и некоторых дополнительных элементов, которые используются для придание форме определённой структуры.
Стилизация формы выполняется через CSS. В этом руководстве остановимся и подробно рассмотрим различные варианты оформления её текстовых полей .
Исходные коды примеров расположены на GitHub в папке text-field проекта «ui-components».
Нормализация стилей
Обычно хорошей практикой считается для всех элементов включая псевдоэлементы установить box-sizing: border-box :
*, *::before, *::after { box-sizing: border-box; }
В этом случае браузер при рассчитывании ширины и высоты элементов будет включать в них поля (padding) и границы (border). Как правило, это сильно упрощает работу с размерами элементов, и избавляет нас от множества проблем при размещении контента.
Для того чтобы в разных браузерах отображался как можно более одинаково необходимо добавить следующее:
/* 1 – Изменим стили шрифтов */ /* 2 – Удалим margin в Firefox и Safari */ input[type="text"] { font-family: inherit; /* 1 */ font-size: inherit; /* 1 */ line-height: inherit; /* 1 */ margin: 0; /* 2 */ }
Базовый вариант оформления input
Для удобного добавления к элементам стилей создадим следующую HTML-разметку:
Т.е. добавим к с type=»text» класс text-field__input , к – text-field__label , а затем обернём их в элемент с классом text-field .
Теперь напишем стили для этих элементов. А также сразу включим в них стили для нормализации, чтобы не добавлять их отдельно:
/* установим отступ 1rem от нижнего края элемента */ .text-field { margin-bottom: 1rem; } /* стили для label */ .text-field__label { display: block; margin-bottom: 0.25rem; } /* стили для input */ .text-field__input { display: block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; font-family: inherit; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-clip: padding-box; border: 1px solid #bdbdbd; border-radius: 0.25rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }
Примененные CSS свойства к элементу , и то, что они делают:
- display: block – устанавливает блочное отображение;
- width: 100% – занимает всю доступную ширину;
- height: calc(2.25rem + 2px) – высота элемента определяется путём сложения 2.25rem ( font-size * line-height + padding-top + padding-bottom ) и 2px (ширина верхней и нижней границы);
- margin: 0 – убирает margin отступы;
- padding: 0.375rem 0.75rem – внутренние поля: сверху и снизу – 0.375rem, а слева и справа – 0.75rem;
- font-family: inherit – чтобы шрифт был такой как у родительского элемента, а не тот который браузер по умолчанию назначает для ;
- font-size: 1rem – устанавливает явный размер шрифта, иначе будет браться из стилей браузера для ;
- font-weight: 400 – задаёт начертание шрифта;
- line-height: 1.5 – высота строки (1.5 * размер шрифта);
- color: #212529 – цвет шрифта;
- background-color: #fff – цвет фона;
- background-clip: padding-box – указывает, что фон (фоновое изображение) нужно рисовать только до внешнего края отступа (под границей не выводить);
- border: 1px solid #bdbdbd – устанавливает границу, у которой: 1px (толщина), solid (тип линии) и #bdbdbd (цвет);
- border-radius: 0.25rem – радиус скругления углов;
- transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out – выполняет изменение значений свойств border-color и box-shadow с анимацией длительностью 0.15 секунд посредством временной функцией ease-in-out .
В результате получили следующее оформление:
Стилизуем плейсхолдер . По умолчанию плейсхолдер отображается полупрозрачным или светло-серым цветом. Получить его можно с помощью ::placeholder . Оформим его следующим образом:
.text-field__input::placeholder { color: #212529; opacity: 0.4; }
Стили для в состоянии фокуса (получить это состояние можно с помощью псевдокласса :focus ):
.text-field__input:focus { color: #212529; background-color: #fff; border-color: #bdbdbd; outline: 0; box-shadow: 0 0 0 0.2rem rgba(158, 158, 158, 0.25); }
Оформление , когда он находится в состоянии disabled и readonly :
Этот набор стилей будет у нас отправной точкой для создания других.
input с иконкой
Рассмотрим пример вставки в input иконки с помощью псевдоэлементов.
Для этого дополнительно обернём элемент в с классами text-field__icon text-field__icon_email :
Первый класс ( text-field__icon ) будем использовать для того, чтобы установить относительное позиционирование ( position: relative ). Это действие позволит нам разместить иконку в нужном месте относительно input , используя уже абсолютное позиционирование ( position: absolute ). Второй класс ( text-field__icon_email ) будет определять иконку, которую мы хотим вставить.
.text-field__icon { position: relative; } .text-field__icon::before { content: ''; color: #bdbdbd; position: absolute; display: flex; align-items: center; top: 0; bottom: 0; left: 0.625rem; top: 50%; transform: translateY(-50%); } .text-field__icon .text-field__input { padding-left: 2rem; } /* email значок */ .text-field__icon_email::before { content: '@'; } /* иконка лупы */ .text-field__icon_search::before { width: 1rem; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23bdbdbd' viewBox='0 0 16 16'%3E%3Cpath d='M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'%3E%3C/path%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: center; }
Ещё один вариант оформления:
input с активной svg-иконкой
В этом примере поместим в input иконку, на которую можно нажать.
Для этого мы также как и в предыдущем примере обернули в . . Саму svg-иконку обернули в с классом text-field__aicon и поместили рядом с .
.text-field__icon { position: relative; } .text-field__icon input { padding-right: 2.5rem; } .text-field__aicon { position: absolute; display: flex; align-items: center; top: 0; bottom: 0; right: 0.875rem; width: 1rem; cursor: pointer; color: #bdbdbd; transition: color 0.15s ease-in-out; } .text-field__aicon:hover { color: #212529; }
Ещё пример вставки иконки в input :
input с кнопкой
HTML-разметка input с кнопкой:
Расположение кнопки справа от input выполним с помощью флексов:
.text-field__group { display: flex; } /* кнопка */ .text-field__btn { display: inline-block; font-weight: 400; line-height: 1.5; color: #212529; text-align: center; vertical-align: middle; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; user-select: none; background-color: #eee; border: 1px solid #bdbdbd; padding: .375rem .75rem; font-size: 1rem; border-radius: .25rem; transition: background-color .15s ease-in-out; } .text-field__btn:hover { background-color: #bdbdbd; } .text-field__group .text-field__input { border-top-right-radius: 0; border-bottom-right-radius: 0; position: relative; z-index: 2; } .text-field__group .text-field__btn { position: relative; border-top-left-radius: 0; border-bottom-left-radius: 0; border-left-width: 0; }
input с плавающим label
Разметка input с плавающим label:
Когда указано значение value:
.text-field_floating { position: relative; } .text-field_floating .text-field__input { height: calc(3.5rem + 2px); line-height: 1.25; padding: 1rem 0.75rem; } .text-field_floating .text-field__label { position: absolute; top: 0; left: 0; height: 100%; padding: 1rem .75rem; pointer-events: none; border: 1px solid transparent; transform-origin: 0 0; transition: opacity .15s ease-in-out, transform .15s ease-in-out; } .text-field_floating .text-field__input::-moz-placeholder { color: transparent; } .text-field_floating .text-field__input::placeholder { color: transparent; } .text-field_floating .text-field__input:focus, .text-field_floating .text-field__input:not(:placeholder-shown) { padding-top: 1.625rem; padding-bottom: .625rem; } .text-field_floating .text-field__input:focus~.text-field__label, .text-field_floating .text-field__input:not(:placeholder-shown)~.text-field__label { opacity: .65; transform: scale(.85) translateY(-.75rem) translateX(.15rem); }
Ещё один вариант с «плавающей» меткой:
input со счётчиком символов
Пример в котором под input отображается количество набранных символов и максимальная длина:
Это выполняется посредством следующего кода:
Стили для отображения состояния валидации input
Применить стили в зависимости от состояния поля в CSS можно с помощью специальных псевдоклассов. Например, :valid позволяет выбрать валидные элементы, а :invalid — не валидные.
.text-field__input:invalid, .text-field__input:valid { border-color: #dc3545; padding-right: 2.25rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right 0.5625rem center; background-size: 1.125rem 1.125rem; } .text-field__input:valid { border-color: #198754; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); } .text-field__input:invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .text-field__input:valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgb(25 135 84 / 25%); }
Но, если вы хотите контролировать этот процесс и добавлять стили с помощью JavaScript, то тогда лучше это делать через классы. Например, использовать класс text-field__input_valid при успешной валидации, а text-field__input_invalid — при не успешной. Их следует добавлять к .
Укажите город. Отлично!
Отображать сообщения пользователю или подсказки можно через
.
Пример валидации формы с помощью JavaScript
Валидацию элементов формы будем осуществлять с помощью функции checkValidity() . После этого, в зависимости от её результата, будем добавлять той или иной класс к , а также сообщение ( input.validationMessage ) в элемент .text-field__message .
// input - переменная, содержащая элемент if (input.checkValidity()) { input.classList.add('text-field__input_valid'); input.nextElementSibling.textContent = 'Отлично!'; } else { input.classList.add('text-field__input_invalid'); input.nextElementSibling.textContent = input.validationMessage; }
Т.к. мы будем сами отображать сообщения, то необходимо отключить стандартные подсказки браузера. Для этого к тегу необходимо добавить атрибут novalidate :
Клиентская проверка формы после нажатия «Отправить»:
Пример валидации формы в реальном времени:
Отображение только ошибок: