От автора: поле ввода в HTML простое, мощное и выполняет то, для чего предназначено. Имея более 30 вариантов атрибутов, input является одним из самых надежных HTML-тегов.
Поскольку пользователи постоянно взаимодействуют с полями на странице, прилагается много усилий, чтобы сделать их привлекательными и простыми для взаимодействия, но многое может пойти не так.
Базовая разметка
Хорошее практическое правило и на самом деле лучшая практика CSS — всегда добавлять метки. В этой статье я буду использовать поле, вложенное внутри label, которое неявно связывает label и тег input вместе и устраняет необходимость указывать атрибут «for» для label и «id» для input, не говоря уже о том, что это также позволяет очень легко стилизовать поле.
1 2 3 4 |
<label class="custom-field"> <input type="email"/> <span class="placeholder">Enter Email</span> </label> |
Другой альтернативой было бы использование тега div в качестве оболочки для таких вещей, как позиционирование, чтобы у них был общий родительский элемент. Тег fieldset также может иметь смысл в некоторых случаях. Этот метод упаковки позволяет размещать label и input рядом, и рассматривать их как единое целое.
1 2 3 4 |
<div class="custom-field"> <input id="email-field" type="email"/> <label for="email-field" class="placeholder">Enter Email</label> </div> |
Еще более короткая и все еще действующая альтернатива — использовать тег label с input внутри, но с атрибутом aria-label для программ чтения с экрана, а затем использовать псевдоэлемент CSS after для создания элемента placeholder.
1 2 3 |
<label class="custom-field" aria-label="Enter Email"> <input type="email"/> </label> |
1 2 3 4 |
// create the placeholder element .custom-field::after { content: attr(aria-label); } |
Все эти три альтернативы будут работать со стилем, который мы будем делать до конца этой статьи. Ниже вы можете видеть, что все три параметра отображают на странице одно и то же. Я использую браузер Chrome, чтобы посмотреть на результат.
Если вы спросите, зачем ставить label после input — это потому, что мы можем использовать состояния ввода, такие как “focus” и другие, для нацеливания на label и управления ее внешним видом и анимацией. Альтернативой может быть использование javascript, что выходит за рамки этого руководства.
Начальная настройка
Обычно я использую нормализаторы CSS, но в случае, если вы этого не сделаете, вы можете включить border-box и box-sizing для установки точного размера и отступа. Если ваше поле не выглядит так, как в этой статье, вероятно, потому, что вам нужен этот фрагмент кода:
1 2 3 |
*, *::before, *::after { box-sizing: border-box; } |
Базовый стиль
Для этого поля я выберу очень простой и минималистичный вид, который мы можем улучшить по мере написания кода.
Для этого поля, текст будет иметь размер 14 пикселей, и поскольку я хочу разместить элемент “placeholder” поверх input, мне нужно установить относительное положение.
1 2 3 4 |
.custom-field { font-size: 14px; position: relative; } |
Стиль поля input в основном предназначен для его сброса, например удаления внешнего вида и границы. Обратите внимание, что ширина input определяет размер элемента custom-field, и еще одна важная деталь — это отступы, которые нам нужно будет сопоставить при размещении элемента placeholder.
1 2 3 4 5 6 7 8 9 10 11 12 |
.custom-field input { border: none; -webkit-appearance: none; -ms-appearance: none; -moz-appearance: none; appearance: none; background: #f2f2f2; padding: 12px; border-radius: 3px; width: 250px; font-size: 14px; } |
Теперь для нашего placeholder я позиционирую его в абсолютном левом углу, чтобы он соответствовал отступу 12 пикселей, и использую преобразование для выравнивания по вертикали с -50% и верхним пределом 22 пикселей, которые вам нужно провести, чтобы сделать его идеально центрированным. Верхние 50% также работают, но я использую пиксели здесь для сообщения об ошибке, которое мы проверим позже.
Чтобы позаботиться о потенциально длинном тексте в placeholder, чего, кстати, никогда не должно быть, я ограничиваю его ширину до 100% минус 24 пикселя, где 24 — это результат суммы левого и правого отступов. Затем я установил переполнение как ellipsis.
1 2 3 4 5 6 7 8 9 10 11 12 |
.custom-field .placeholder { position: absolute; left: 12px; bottom: 50%; top: 22px; transform: translateY(-50%); width: calc(100% - 24px); color: #aaa; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } |
Вы можете использовать здесь переменную CSS, чтобы убедиться, что если вы позже измените отступы, placeholder также будет изменён.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.custom-field { ... --field-padding: 12px; } .custom-field input { ... padding: var(--field-padding); } .custom-field .placeholder { ... left: var(--field-padding); width: calc(100% - (var(--field-padding) * 2)); } |
Эффект плавающего поля label
Теперь, когда мы нажимаем на поле, placeholder сжимается и перемещается в верхний левый угол над полем.
Для этого нам сначала нужно иметь некоторое пространство над полем для перемещения placeholder -a и для минимального пространства, необходимого, если перед ним появляется другой элемент. Для этого 20 пикселей по верхнему краю идеально подходят, чтобы label оставалась центрированной по отношению к блоку, а граница считалась внешней частью.
1 2 3 4 |
.custom-field { ... border-top: 20px solid transparent; } |
Теперь нам нужно знать, когда input получает фокус для анимации placeholder-а. Поэтому, когда поле получает фокус, мы будем использовать комбинатор для нацеливания на placeholder и изменения шрифта на меньший размер, темный цвет и сдвиг вверх на 10 пикселей.
1 2 3 4 5 |
.custom-field input:focus + .placeholder { top: -10px; font-size: 10px; color: #222; } |
Теперь проблема в том, что если поле имеет значение и не имеет фокуса, мы также хотим, чтобы placeholder оставался активным. Для этого есть много альтернатив. Мы могли бы использовать псевдокласс :valid вместе с атрибутом required, но проблема в том, что он работает только для обязательных полей.
1 |
<input type="email" required/> |
1 2 3 4 5 |
// if required field is valid means it has value // if more validation rules is specified this may break input:valid + .placeholder { ... } |
Другой альтернативой является использование javascript для установки класса, когда поле имеет значение или нет, но это руководство предназначено только для CSS, поэтому решение – это использовать “placeholder-shown” вместе с непустым атрибутом placeholder-а.
1 2 3 4 |
// the placeholder must NOT be empty // for this to work and is simply // a empty space <input type="email" placeholder=" "/> |
1 2 3 4 5 |
// if the placeholder is not shown // it means the user started to type value input:not(:placeholder-shown) + .placeholder { ... } |
Теперь, чтобы воспользоватся возможностью иметь красивую анимацию, мы можем добавить переход к верхнему краю, размер шрифта и цвет к элементу placeholder-а.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.custom-field .placeholder { ... transition: top 0.3s ease, color 0.3s ease, font-size 0.3s ease; } .custom-field input:not(:placeholder-shown) + .placeholder .custom-field input:focus + .placeholder { top: -10px; font-size: 10px; color: #222; } |
Отображение сообщение об ошибке
В зависимости от формы вам может потребоваться, а может и не потребоваться показывать сообщение об ошибке прямо в поле. Для тега label вы можете включить другой элемент ошибки.
1 2 3 4 5 |
<label class="custom-field"> <input type="email" placeholder=" "/> <span class="placeholder">Enter Email</span> <span class="error-message" aria-live="polite"></span> </label> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.custom-field { ... margin-bottom: 24px; } .custom-field .error-message { width: 100%; display: flex; align-items: center; padding: 0 8px; font-size: 12px; background: #d30909; color: #fff; height: 24px; } .custom-field .error-message:empty { opacity: 0; } |
Большой трюк здесь в том, что поле ошибки занимает всю ширину и, естественно, находится под полем. Вы также можете проверить, есть ли ошибка, и показать элемент сообщения об ошибке. В общем, я предпочитаю использовать непрозрачность, чтобы не было разницы между отображением ошибки или ее отсутствием, но вы можете делать все, что захотите.
Атрибут aria-live указывает, что об этом следует сообщить всем, включая программы чтения с экрана. Соответствуюшее значение указывает, как следует сообщить об ошибке пользователю. В этом сценарии такой атрибут строго необходим, чтобы помочь путаницей с текстом в теге label.
Что дальше?
Эти методы организации разметки, чтобы поле выглядело красиво, без ущерба для доступности и SEO, имеют большое значение и могут использоваться в качестве основы для многих удивительных полей.
Я хотел бы показать вам больше, пригласив вас посмотреть видео о стилизации классных полей ввода или проверить исходный код для получения более подробной информации об этих методах.
Автор: Before Semicolon
Источник: medium.com
Редакция: Команда webformyself.
Читайте нас в Telegram, VK, Яндекс.Дзен