Анимация label для текстового input

Выпрыгивающий из текстового поля placeholder и переходящий в его подпись (label) выглядит эффектно и давно применяется в веб-формах. Существует множество вариаций этого эффекта, но принцип реализации у них схожий. Когда поле ввода текста пустое, его подпись placeholder размещается внутри и подсказывает пользователям, какое ожидается значение. Как только input получает фокус, placeholder выскакивает наружу, масштабируется и трансформируется в label. Теперь его назначение — напоминать, какую информацию уже ввел пользователь, а не подсказывать, что ожидалось для ввода в поле.

Эта техника — пример прогрессивного UX, когда подписи к полям формы утрачивают важность по мере того, как пользователь продолжает заполнять форму. Утрачивающие по ходу взаимодействия с пользователем важность элементы уходят на второй план, а новые и актуальные перемещаются на передний план.

В этой статье рассматривается пример с использованием «прыгающих» текстовых подписей к полям формы. Для примера используется форма регистрации, где placeholder выпрыгивают из input и попадают в кармашки над ними, становясь label.

прыгающий label для text input

Рассуждения о семантике

Всю HTML-разметку веб-страницы можно сделать с помощью только <div>… </div>. Это легко и часто даже как-то работает. По ситуации div легко стилизовать и получить результат, который будет выглядеть приемлемо. Но такой способ работы обманчив. Многие вещи не будут работать нормально. В частности, у таких веб-страниц будут серьёзные проблемы с доступностью. Многие функции доступности встроены в HTML и работают «из коробки» при правильном применении HTML-элементов. Но если их использовать не по назначению, например заменить кнопки и метки абстрактными элементами, типа div, браузер не получит достаточного представления об их использовании и назначении. Программы чтения с экрана и другие вспомогательные инструменты не смогут правильно интерпретировать эти элементы.

Это плохо не только для доступности, но и для самой HTML-разметки, состоящей из элементов одинакового типа, например, из одних div. Поначалу с этим ещё можно справляться, но по мере развития кода, отсутствие семантики в разметке доставит немало проблем с его поддержкой и расширением. Поэтому следует использовать правильные HTML-элементы в правильном контексте, т.е. в соответствии с их назначением. Так можно бесплатно получить много готовых решений и обойтись без изобретения велосипедов.

В случае с текстовыми полями и метками к ним, для обоих есть соответствующие HTML-элементы: input и label. У HTML-элемента label есть атрибут for, который позволяет связать метку и текстовое поле input. Вот как это выглядит в коде:

<input id="firstname" class="input" type="text" placeholder=" " />
<label for="firstname" class="placeholder">First name</label>

Пробел в значении атрибута placeholder — трюк, позволяющий для управления логикой фокуса использовать только CSS.

Обнаружение изменений при вводе текста

Атрибут placeholder у поля формы позволяет использовать CSS-правило :placeholder-shown. Тогда только с помощью CSS и без Javascript, можно легко определить, есть ли в input значение. Когда значение атрибута placeholder текстового input должно быть видимым, в текстовом поле (из примера кода выше) будет показываться прозрачный пробел. Если браузер показывает содержимое из placeholder, точно известно, что у input нет значения, т.е. поле не заполнено.

После ввода в текстовое поле текста браузер автоматически скрывает его placeholder. Это не будет заметно, поскольку в нём используется прозрачный пробел. Зато технически теперь у текстового поля есть значение, а браузер переключил отображаемое состояние подсказки (placeholder). Это состояние позволяет CSS управлять другими элементами в зависимости от того, есть ли в текстовом поле input какое-нибудь значение или нет.

как работает CSS-правило  :placeholder-shown
Как работает CSS-правило :placeholder-shown

Для того, чтобы добавить эффектный прыжок подсказки из поля наружу, нужны следующие условия:

  1. Фокус помещён в текстовом поле
  2. У input есть какое-то значение. Это рассмотренный выше случай, когда скрывается placeholder.

Вот как написать эти условия в CSS:

.input:focus ~ .label,  /* фокус на input */
.input:not(:placeholder-shown) ~ .label  /* в input есть значение */  {
  transform: translateY(-30px) translateX(10px) scale(0.75);
}

Фрагмент CSS устанавливает стиль подписи-метки в зависимости от состояния текстового поля. Селектор ~ — это то, что соединяет input и следующий после него в HTML-коде label и расположенный на том же уровне. Когда это CSS-правило становится активным, подпись к полю меняет свой внешний вид: перемещается и масштабируется. Т.е. покидает поле ввода и не мешает пользователю печатать в нём.

Чтобы оживить переход состояния метки, можно добавить такой переход.

.label {
  ...
  transition: transform 200ms, color 200ms;
  ...
}

Лучше этот переход разделить на два и таким образом выделять метку, когда фокус переместится в поле ввода текста. Всегда полезно дать пользователю визуальную подсказку о том, где находятся курсор и фокус. Курсор во многих случаях слишком тонкий, поэтому уделить больше внимания тому факту, что фокус перемещен в поле для ввода не повредит.

.input:not(:placeholder-shown) ~ .label {
  color: #808097; /* сероватый */
}
.input:focus ~ .label {
  color: #dc2f55; /* красный, фокус в поле */
}

Кармашки для меток

Для кармашков подойдут контейнеры со скругленными углами того же цвета, что и фон.

кармашки для прыгающих label
кармашки для прыгающих label

На картинке для наглядности цвет контейнеров-кармашков показан ярким и четким. Он иллюстрирует форму HTML-узлов, которые для этого используются.

Может показаться излишним использовать два элемента для label и его подложки вместо того, что окажется одним. Однако так будет проще нарисовать кармашек поверх существующей разметки и добавить ему какие-нибудь трансформации для эффектного появления.

Тогда для перемещения кармашка-подложки можно использовать точно такую ​​же логику трансформации как для текста. Единственное отличие состоит в том, что контейнер со скругленными углами по вертикали перемещается в противоположном направлении навстречу тексту.

.input:focus ~ .pocket,
.input:not(:placeholder-shown) ~ .pocket {
  transform: translateY(8px);
}

Пример

See this code Fancy jumping labels on x.xhtml.ru.

В заключение

Лёгкая анимация элементов формы в ответ на действия пользователя усиливает ощущение ответной реакции, а перемещение подсказок в ответ на изменение состояния поля ввода — хороший пример прогрессивного UX.

Чтобы определить, когда нужно активировать анимацию используется только CSS.

Для демонстрации перемещения подписи-метки поля ввода формы, использован CSS-transition для translate и scale.