От автора: исторически HTML-формы были довольно сложными — во-первых, потому что требовалось хотя бы немного JavaScript, а во-вторых, потому что никакое количество CSS не могло заставить их работать.
Однако это не обязательно верно в случае современного веб, поэтому давайте узнаем, как размечать формы, используя только HTML и CSS.
Базовая структура
Начните с элемента form. Здесь ничего особенного. Покрытие только основной структуры.
<form> ... </form>
Если вы отправляете данные формы естественным образом (то есть без JavaScript), вам необходимо включить атрибут action, в котором значением является URL-адрес, на который вы будете отправлять данные формы. Method должен быть GET или POST — в зависимости от того, чего вы пытаетесь достичь (не отправляйте конфиденциальные данные через GET).
Кроме того, существует также менее используемый атрибут enctype, который определяет тип кодировки отправляемых данных. Кроме того, атрибут target, хотя он не обязательно является уникальным атрибутом форм, может использоваться для отображения вывода на новой вкладке.
Формы на основе JavaScript не обязательно нуждаются в этих атрибутах.
<form method="POST" action="/subscribe" enctype="application/x-www-form-urlencoded" target="_blank"> ... </form>
Формы состоят из полей ввода.
<form> <input type="text"><!-- text input --> <input type="text" value="Prefilled value"> </form>
Включение меток для удобства использования и доступности
Каждому полю нужна метка. Метка — это текстовый дескриптор, описывающий, для чего предназначено поле. Есть три способа объявить метку, но один из них превосходит два других. Давайте сейчас рассмотрим их.
Смежные метки
Смежные метки требуют больше всего кода, потому что нам нужно явно объявить, какое поле описывает метка. Для большинства это противоречит здравому смыслу, потому что вместо этого мы можем обернуть поля в метки, чтобы добиться того же эффекта с помощью меньшего количества кода.
Однако данный метод может потребоваться в определенных обстоятельствах, поэтому вот как это будет выглядеть:
<label for="firstName">First name</label> <input id="firstName">
Как видно из приведенного выше примера, атрибут for объекта label должен соответствовать атрибуту id поля, и это объясняет устройствам ввода, какой текстовый дескриптор принадлежит какому полю. Затем устройство ввода передаст это пользователям (например, программы чтения с экрана будут зачитывать это с помощью речи).
Метки ARIA
Хотя семантический HTML лучше, метки ARIA (Accessible Rich Internet Applications) могут компенсировать их отсутствие. В этом случае вот как может выглядеть метка в отсутствие фактической label HTML:
<input aria-label="First name">
К сожалению, оборотной стороной такого подхода является отсутствие визуальной метки. Однако это может быть хорошо для некоторых разметок (например, форма с одним полем ввода с заголовком и заполнителем):
<h1>Subscribe</h1> <form> <input aria-label="Email address" placeholder="bruce@wayneenterpris.es"> </form>
Заключение полей в метки
Заключение полей ввода в метки — самый чистый подход. Кроме того, благодаря CSS :focus-within мы можем даже стилизовать метки, когда их дочерние элементы выделяются фокусом, но мы рассмотрим это позже.
<label> First name<input> </label>
Заполнители или метки
Краткое сравнение:
Метки указывают, что ожидается в поле ввода
Заполнители показывают примеры указанных ожиданий
Заполнители не предназначены для использования в качестве альтернативы меткам, хотя, как мы видели в приведенном выше примере ARIA, они могут вернуть часть контекста, который теряется из-за отсутствия визуальных меток. Однако в идеале мы должны использовать оба:
<label> First name<input placeholder="Bruce"> </label>
Выбор типов полей ввода
Заполнители применяются только к текстовым элементам ввода, но на самом деле существует целый ряд различных типов полей ввода, в том числе:
<input type="button"> <input type="checkbox"> <input type="color"> <input type="date"> <input type="datetime-local"> <input type="email"> <input type="file"> <input type="hidden"> <!-- explained later --> <input type="image"> <input type="month"> <input type="number"> <input type="password"> <input type="radio"> <input type="range"> <input type="reset"> <input type="search"> <input type="submit"> <!-- submits a form --> <input type="tel"> <input type="text"> <!-- the default --> <input type="time"> <input type="url"> <input type="week">
Семантические типы элементов ввода полезны во время валидации формы, особенно при использовании пользовательской валидации, которую мы вскоре рассмотрим. Во-первых, давайте узнаем, как стилизовать эти поля.
Стилизация полей ввода
Возможно, наиболее раздражающим аспектом кодирования форм является переопределение стиля браузера по умолчанию. К счастью, сегодня по данным caniuse.com 96,06% браузеров поддерживают appearance: none;.
После сброса стиля веб-браузера по умолчанию с помощью следующего кода CSS мы можем стилизовать поля ввода так, как захотим, и это даже включает переключатели и чек-боксы:
input { -webkit-appearance: none; -moz-appearance: none; appearance: none; ... }
Однако некоторые из этих элементов могут иметь причуды, которые трудно или даже невозможно преодолеть (в зависимости от веб-браузера). По этой причине многие разработчики склонны возвращаться к значению по умолчанию type=»text» для attribute = value, если они находят эти причуды нежелательными (например, раскладка для input type=»number»). Тем не менее, есть универсальные решения…
Указание inputmode
По данным caniuse.com, при поддержке 82,3% веб-браузеров новый атрибут inputmode указывает, какая раскладка клавиатуры будет отображаться на портативных устройствах независимо от используемого ввода type. Лучше, чем ничего, правда?
<input type="text" inputmode="none"> <!-- no keyboard --> <input type="text" inputmode="text"> <!-- default keyboard --> <input type="text" inputmode="decimal"> <input type="text" inputmode="numeric"> <input type="text" inputmode="tel"> <input type="text" inputmode="search"> <input type="text" inputmode="email"> <input type="text" inputmode="url">
Валидация ввода пользователя
Если вы выберете нативную валидацию HTML вместо решения на JavaScript, помните, что inputmode ничего не дает в этом отношении. inputmode=»email» не будет проверять адрес электронной почты, тогда как input type=»email» будет. Вот в чем разница.
Отложив это в сторону, давайте рассмотрим, что запускает валидацию:
<input required> <!-- value is required --> <form required> <!-- all values are required --> <!-- alternative input types --> <input type="email"> <!-- blank or a valid email address --> <input type="email" required> <!-- must be a valid address --> <!-- text-based inputs --> <input minlength="8"> <!-- blank or min 8 characters --> <input maxlength="32"> <!-- blank or max 32 characters --> <input maxlength="32" required> <!-- max 32 characters --> <!-- numeric-based inputs --> <input type="date" min="yyyy-mm-dd"> <!-- min date --> <input type="number" max="66" required> <!-- max number -->
Создание собственных правил
Пользовательские правила требуют знания регулярных выражений JavaScript, используемых объектом RegExp (но без использования косой черты или кавычек). Вот пример, в котором используются символы нижнего регистра (a – z) и минимальная / максимальная длина в одном правиле:
<input pattern="[a-z]{8,12}">
Больше информации вы найдете здесь.
Примечание: внешняя валидация (нативная HTML или другая) никогда не должна использоваться в качестве замены валидации на стороне сервера!
Стилизация допустимых / недопустимых состояний
Просто для большей ясности вот как мы обозначим валидность:
input:valid { border-left: 1.5rem solid lime; } input:invalid { border-left: 1.5rem solid crimson; } form:invalid { /* this also works, technically! */ }
Элементы ввода пытаются немедленно проверить значения (или их отсутствие), поэтому следующий код (который показывает только допустимые / недопустимые состояния, в то время как поле содержит значение) может быть лучше:
input:not(:placeholder-shown):valid { border-left: 1.5rem solid lime; }
Это показывает допустимый / недопустимый стиль, но только тогда, когда заполнитель не отображается (потому что пользователь что-то ввел).
Прочие базовые вещи
Отправка данных формы
Для отправки данных формы на сервер обычно требуется, чтобы элементы ввода содержали атрибут name. Это также относится к скрытым полям:
<input type="email" name="email"> <input type="hidden" name="email" value="{{ user.email }}">
Принятие полей длинной формы
По сути, textarea — это то же самое <input type=»text»>, за исключением того факта, что текстовые поля поддерживают многострочность. Да, <input type=»textarea»>, конечно, было бы более интуитивно понятно, но, увы, textarea — это корректный способ принимать данные от пользователей в длинной форме. Кроме того, он принимает большинство (если не все) атрибутов, которые используются в элементах ввода.
Группировка полей для лучшей доступности
Хотя более короткие формы предлагают гораздо лучший пользовательский опыт, иногда неизбежны более длинные формы. В таком сценарии элемент fieldset может использоваться для содержания связанных полей, при этом для дочернего элемента может использоваться legend в качестве заголовка для fieldset:
<fieldset> <legend>Name</legend> <input type="text" name="title"> <input type="text" name="firstName"> <input type="text" name="lastName"> </fieldset> <fieldset> <legend>Contact details</legend> <input type="email" name="email"> <input type="tel" name="homePhone"> <input type="tel" name="mobilePhone"> </fieldset>
Полезные вещи
Отключение полей ввода
Добавление атрибута disabled может сделать поле (или любой фокусируемый элемент) несуществующим, хотя это обычно применяется / не применяется через JavaScript. Но вот как это работает:
<form disabled>...</form> <fieldset disabled>...</fieldset> <input type="submit" disabled>
И сопутствующий CSS, если необходимо:
:enabled { opacity: 1; } :disabled { opacity: 0.5; }
Однако если все, что вы хотите сделать, это добавить дополнительную визуальную подсказку, указывающую на то, что ввод пользователя недействителен, вы, скорее всего, захотите использовать общий комбинатор (~). Следующий код в основном означает «кнопку отправки данных, которая следует за любым элементом с недопустимым вводом». Это не меняет никаких функций, но когда мы используем нативную HTML-валидацию формы (которая обрабатывает отключение / включение возможности отправки автоматически), это нормально:
:invalid ~ input[type=submit] { opacity: 0.5; }
Отключение поля, но отправка данных в любом случае
Сочетание <input disabled> и <input type=»hidden»> в следующем примере гарантирует, что значение нельзя изменить. Разница в том, что, в отличие от disabled, значения readonly отправляются как данные формы; и в отличие от hidden, readonly видимо:
<input readonly value="Prefilled value">
Изменение увеличения значений
Числовые поля ввода имеют «вращающуюся кнопку» для настройки числового значения, а также принимают атрибут step, который определяет альтернативное значение увеличения значения каждой настройки:
<input type="number" step="0.1" max="1">
Стилизация форм, меток и наборов полей, выделенных фокусом
Мы можем использовать focus-within: для стилизации любого родительского элемента ввода, который в настоящее время выделен фокусом. Скорее всего, этот элемент будет контейнером для form, label или fieldset:
form:focus-within, fieldset:focus-within, label:focus-within { ... }
Отправка нескольких значений через одно поле
multiple действительно для таких типов элементов ввода, как file и email:
<input multiple type="file"> <!-- multiple files --> <input multiple type="email"> <!-- comma-separated emails -->
Написание сокращенного кода формы
Если форма состоит только из единственного элемента button, <input type=»image»> или <input type=»submit»>, существует сокращенный метод разметки HTML-форм. Вот пример:
<input type="image" formaction formmethod formenctype formtarget>
В отличие от этого:
<form action method enctype target> <input type="image"> </form>
Я что-то пропустил?
HTML сейчас намного более интуитивно понятен, чем, скажем, 10 лет назад. Он постоянно развивается, и, несомненно, в свое время будет что-то еще, что добавят по теме форм HTML / CSS. Один из примеров, который приходит на ум — это элемент datalist, который на данный момент может содержать довольно много ошибок (особенно в Firefox). Но кроме этого, я что-нибудь пропустил?
В заключение отмечу, что есть некоторые аспекты HTML-форм, которые я не рассматривал, потому что их использование не рекомендуется, в том числе:
Autofocus (плохо для доступности)
Autocomplete (не используя автозаполнение, мы предоставляем выбор пользователю)
Accesskey (плохая поддержка и доступность)
Novalidate (без JavaScript это бесполезно)
Автор: Daniel Schwarz
Источник: www.sitepoint.com
Редакция: Команда webformyself.