Как структурировать HTML-формы
==============================

* Назад
* Обзор: Forms
* Далее

Получив базовые знания, теперь мы более подробно рассмотрим элементы, используемые для придания структуры и значения различным частям форм.

| Уровень подготовки: | Основы компьютерной грамотности, и базовые знания HTML. |
| --- | --- |
| Цель: | Разобраться как структурировать HTML формы и задавать им семантику для того, чтобы они были удобны и доступны в использовании. |

Гибкость HTML форм делает их одной из самых сложных структур в HTML; вы можете создать любую форму, используя элементы и атрибуты форм. Использование правильной структуры, при создании HTML форм, поможет гарантировать их удобство и доступность.

Элемент <form>
--------------

Элемент `<form>` формально определяет форму и атрибуты, которые определяют поведение этой формы. Каждый раз, когда вы хотите создать HTML-форму, вам нужно начать с создания элемента `<form>`, поместив внутрь него всё содержимое. Многие вспомогательные технологии или браузерные плагины могут обнаруживать элементы `<form>` и реализовывать специальные хуки, чтобы их было проще использовать.

Мы уже встречались с этим в предыдущей статье.

**Предупреждение:** **Внимание:** Строго запрещается размещать форму внутри другой формы. Такое размещение может привести к непредсказуемому поведению форм, в зависимости от браузера.

Стоит учесть, что всегда можно использовать элементы формы вне `<form>`. Тогда по умолчанию этот элемент формы не имеет ничего общего со всеми формами. Вы можете связать его с формой с помощью атрибута `form`. В HTML5 был представлен атрибут `form` для элементов HTML форм, который позволяет явно связать элемент с формой, даже если он не заключён внутри `<form>`.

Элементы <fieldset> и <legend>
------------------------------

Элемент `<fieldset>` - это удобный способ стилистической и семантической группировки элементов формы. Вы можете установить заголовок `<fieldset>`, добавив элемент `<legend>` сразу после открывающего тега `<fieldset>`. Текст элемента `<legend>` формально описывает назначение содержимого `<fieldset>`.

Различные вспомогательные технологии будут использовать `<legend>` как часть метки `label` всех элементов внутри `<fieldset>`. Например, такие экранные дикторы как Jaws или NVDA произносят заголовок формы `<legend>` перед произношением названия меток элементов.

Небольшой пример:


```html
<form>
  <fieldset>
    <legend>Fruit juice size</legend>
    <p>
      <input type="radio" name="size" id="size\_1" value="small" />
      <label for="size\_1">Small</label>
    </p>
    <p>
      <input type="radio" name="size" id="size\_2" value="medium" />
      <label for="size\_2">Medium</label>
    </p>
    <p>
      <input type="radio" name="size" id="size\_3" value="large" />
      <label for="size\_3">Large</label>
    </p>
  </fieldset>
</form>
```


**Примечание:** вы можете найти этот пример в fieldset-legend.html (также посмотрите на результат).

Читая эту форму, экранный диктор произнесёт "Fruit juice size small" для первого элемента, "Fruit juice size medium" - для второго, "Fruit juice size large" - для третьего.

Вариант использования в этом примере является одним из наиболее важных. Каждый раз, когда у вас есть набор переключателей, вам нужно поместить их внутри `<fieldset>`. Также `<fieldset>` можно использовать для разделения формы. В идеале, длинную форму разделяют на несколько страниц, однако, если она должна находиться на одной странице, распределение связанных элементов в разные `<fieldset>` может повысить удобство использования.

Из-за своего влияния на вспомогательные технологии элемент `<fieldset>` является одним из ключевых элементов для построения доступных форм; однако вы не должны им злоупотреблять. Если возможно, старайтесь проверять, как экранный диктор интерпретирует вашу форму.

Элемент <label>
---------------

В предыдущей статье мы увидели, что элемент `<label>` принято использовать для указания текстов-подсказок (лейблов) в HTML-формах. Это самый важный элемент для построения доступных форм — при правильной реализации скринридеры будут озвучивать текст-подсказку вместе со связанными элементами. Посмотрите на этот пример из предыдущей статьи:


```html
<label for="name">Name:</label> <input type="text" id="name" name="user\_name" />
```


При правильно связанном элементе `<label>` с элементом `<input>` через атрибуты `for` и `id` соответственно (атрибут `for` ссылается на атрибут `id` соответствующего виджета формы), скринридер прочтёт вслух что-то наподобие "Name, edit text".

Если `<label>` не правильно установлен, скринридер прочитает это как "Edit text blank", что не несёт в себе никакой уточняющей информации, позволяющей понять предназначение данного текстового поля.

Обратите внимание на то, что виджет формы может быть вложен в элемент `<label>`, как на примере:


```html
<label for="name">
  Name: <input type="text" id="name" name="user\_name" />
</label>
```


Однако даже в таких случаях лучше всё равно указывать атрибут `for`, так как некоторые вспомогательные технологии не распознают неявную связь между текстами-подсказками и виджетами.

### Лейблы тоже кликабельны!

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

Например:


```html
<form>
  <p>
    <label for="taste\_1">I like cherry</label>
    <input type="checkbox" id="taste\_1" name="taste\_cherry" value="1" />
  </p>
  <p>
    <label for="taste\_2">I like banana</label>
    <input type="checkbox" id="taste\_2" name="taste\_banana" value="2" />
  </p>
</form>
```


**Примечание:** вы можете посмотреть этот пример тут checkbox-label.html (также можно посмотреть код вживую).

### Несколько лейблов

На самом деле вы можете добавить несколько текстов-подсказок на один виджет формы, но это не очень хорошая идея, так как у некоторых вспомогательных технологий могут возникнуть проблемы с обработкой такой структуры. Вместо использования нескольких лейблов, лучше вложить виджет формы внутрь одного элемента `<label>`.

Рассмотрим этот пример:


```html
<p>Required fields are followed by <abbr title="required">*</abbr>.</p>

<!-- Тогда это: -->
<div>
  <label for="username">Name:</label>
  <input type="text" name="username" />
  <label for="username"><abbr title="required">*</abbr></label>
</div>

<!-- лучше сделать таким образом: -->
<div>
  <label for="username">
    <span>Name:</span>
    <input id="username" type="text" name="username" />
    <abbr title="required">*</abbr>
  </label>
</div>

<!-- Но этот вариант лучше всего: -->
<div>
  <label for="username">Name: <abbr title="required">*</abbr></label>
  <input id="username" type="text" name="username" />
</div>
```


Параграф на первой строке примера описывает правило для обязательных элементов. Вначале необходимо убедиться, что вспомогательные технологии, такие как программы чтения с экрана, отображают или озвучивают их пользователю, прежде чем он найдёт требуемый элемент. Таким образом они будут знать, что означает звёздочка. Программа чтения с экрана будет произносить звёздочку как «звёздочку» или «обязательно», в зависимости от настроек программы чтения с экрана — в любом случае, первый абзац даёт понимание того, что будет означать звёздочка далее в форме.

* В первом примере лейбл не будет прочитан вместе с текстовым полем — получится лишь "edit text blank" и отдельно читаемые тексты-подсказки. Множественные элементы `<label>` могут быть неправильно интерпретированы программой чтения с экрана.
* Второй пример немного лучше — лейбл будет прочитан вместе с текстовым полем и будет звучать как "name star name edit text", однако тексты-подсказки всё ещё разделены. Это всё ещё немного сбивает с толку, но на этот раз ситуация немного лучше, потому что с текстовое поле связано с текстом-подсказкой.
* Третий пример — лучший, так как весь лейбл будет связан с текстовым полем и озвучен целиком, а при чтении текст будет звучать как "name star edit text".

**Примечание:** В зависимости от программы для чтения с экрана результаты могут немного отличаться. В данной статье для тестирования использовался VoiceOver (NVDA ведёт себя аналогично). Также мы были бы рады, если бы вы поделились своим опытом.

**Примечание:** вы можете найти этот пример на GitHub required-labels.html (также можно посмотреть вживую). Запускайте пример, закомментировав остальные, иначе скриридеры не смогут правильно распознать контент, если у вас будет несколько лейблов и несколько текстовых полей с одинаковым ID!

Часто используемые с формами HTML-структуры
-------------------------------------------

Помимо структур, характерных только для HTML-форм, хорошо помнить, что формы — это просто HTML. Это означает, что вы можете использовать всю мощь HTML для структурирования HTML-формы.

Как вы можете заметить в примерах, оборачивать лейбл и виджет формы в элемент `<div>` — это общепринятая практика. Элемент `<p>` также часто используется, как и HTML-списки (последние часто используются для структурирования множественных чекбоксом или радио-кнопок).

В добавок к элементу `<fieldset>` часто используют HTML-заголовки (например, `<h1>` (en-US), `<h2>` (en-US)) и секционирование (например, `<section>`) для структурирования сложных форм.

Прежде всего, вам нужно найти стиль, который будет удобен именно вам для программирования и который также позволит создавать доступные и удобные формы.

Каждый отдельный раздел функциональности содержится в элементах `<section>` и `<fieldset>`, содержащий переключатели. Каждый отдельный раздел функциональности должен находиться в отдельном элементе `<section>` с элементами `<fieldset>`, содержащими переключатели.

### Активное обучение: построение структуры формы

Давайте применим эти идеи на практике и построим более сложноструктурируемую форму — формы оплаты. Форма будет содержать некоторые типы виджетов формы, которые вы можете пока не понять — не переживайте об этом, вы найдёте информацию в следующей статье (Основные нативные элементы управления формами (en-US)). А пока внимательно прочитайте описание, следуя приведённым ниже инструкциям, и начинайте формировать представление о том, какие элементы обёртки мы используем для структурирования формы и почему.

1. Для начала сделайте локальную копию пустого шаблона и CSS для нашей платёжной формы в новой директории на вашем компьютере.
2. Сначала подключите CSS к HTML, добавив следующую строку кода внутрь HTML-элемента `<head>`:

```html
<link href="payment-form.css" rel="stylesheet" />
```

3. Далее начните создавать свою форму с добавления внешнего элемента `<form>`:

```html
<form></form>
```

4. Внутри тега `<form>`, добавьте заголовок и параграф, информирующий пользователей о том, как помечены поля, обязательные для заполнения:

```html
<h1>Payment form</h1>
<p>
  Required fields are followed by
  <strong><abbr title="required">*</abbr></strong
 >.
</p>
```

5. Далее нам надо добавить более крупный кусок кода под нашей предыдущей записью. Здесь вы можете увидеть, что мы оборачиваем поля с контактной информацией в отдельный элемент `<section>`. Более того, у нас есть набор из двух радио-кнопок, каждую из которых мы помещаем в отдельный элемент списка (`<li>`). Наконец, у нас есть два текстовых поля `<input>` и связанные с ними элементы `<label>`, которые находятся внутри элементов `<p>`, а также поле для ввода пароля. Добавьте этот код в вашу форму:

```html
<section>
  <h2>Contact information</h2>
  <fieldset>
    <legend>Title</legend>
    <ul>
      <li>
        <label for="title\_1">
          <input type="radio" id="title\_1" name="title" value="M." />
          Mister
        </label>
      </li>
      <li>
        <label for="title\_2">
          <input type="radio" id="title\_2" name="title" value="Ms." />
          Miss
        </label>
      </li>
    </ul>
  </fieldset>
  <p>
    <label for="name">
      <span>Name: </span>
      <strong><abbr title="required">*</abbr></strong>
    </label>
    <input type="text" id="name" name="username" />
  </p>
  <p>
    <label for="mail">
      <span>E-mail: </span>
      <strong><abbr title="required">*</abbr></strong>
    </label>
    <input type="email" id="mail" name="usermail" />
  </p>
  <p>
    <label for="pwd">
      <span>Password: </span>
      <strong><abbr title="required">*</abbr></strong>
    </label>
    <input type="password" id="pwd" name="password" />
  </p>
</section>
```

6. Сейчас мы перейдём к второму разделу `<section>` нашей формы — платёжной информации. В этом разделе у нас есть три отдельных виджета формы со связанными с ними лейблами, находящимися внутри тега `<p>`. Первый — это выпадающее меню (`<select>`) для выбора типа кредитной карты. Второй — это элемент `<input>` с типом `number` для ввода номера карты. Последний виджет — это элемент `<input>` с типом date для указания даты окончания действия карты (должен будет появиться виджет с выбором даты или обычное текстовое поле в браузерах, не поддерживающих данные тип). Более новые типы полей описаны в статье The HTML5 input types (en-US).
 Вставьте следующий код под предыдущим разделом:

```html
<section>
  <h2>Payment information</h2>
  <p>
    <label for="card">
      <span>Card type:</span>
    </label>
    <select id="card" name="usercard">
      <option value="visa">Visa</option>
      <option value="mc">Mastercard</option>
      <option value="amex">American Express</option>
    </select>
  </p>
  <p>
    <label for="number">
      <span>Card number:</span>
      <strong><abbr title="required">*</abbr></strong>
    </label>
    <input type="number" id="number" name="cardnumber" />
  </p>
  <p>
    <label for="date">
      <span>Expiration date:</span>
      <strong><abbr title="required">*</abbr></strong>
      <em>formatted as mm/yy</em>
    </label>
    <input type="date" id="date" name="expiration" />
  </p>
</section>
```

7. Последняя секция, которую мы добавим выглядит намного проще и содержит в себе только элемент `<button>` с типом `submit`, для отправки данных. Добавьте этот код в конец вашей формы:

```html
<p><button type="submit">Validate the payment</button></p>
```


Вы можете увидеть законченную форму в действии ниже (также её можно найти на GitHub — посмотрите payment-form.html и живой пример):

Протестируйте себя!
-------------------

Вы дошли до конца статьи, но можете ли вспомнить самую важную информацию? Далее вы можете найти тест, который поможет убедиться, что вы усвоили знания прежде чем двигаться дальше — посмотрите Test your skills: Form structure (en-US).

Заключение
----------

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

Смотрите также
--------------

* A List Apart: *Sensible Forms: A Form Usability Checklist*
* Назад
* Обзор: Forms
* Далее
В этом разделе
--------------

* Ваша первая HTML форма
* Как структурировать HTML-формы
* Стандартные виджеты форм
* The HTML5 input types (en-US)
* Other form controls (en-US)
* Стили HTML-форм
* Advanced form styling (en-US)
* UI pseudo-classes (en-US)
* Проверка данных формы
* Отправка данных формы
### Дополнительные темы

* Как создавать пользовательские виджеты форм
* Sending forms through JavaScript
* Property compatibility table for form widgets (en-US)