18 сентября 2010 в 16:02

HTML5 для веб-дизайнеров. Часть 4: Формы 2.0 перевод

HTML5 для веб-дизайнеров

  1. Краткая история языка разметки
  2. Модель HTML5
  3. Мультимедиа
  4. Формы 2.0
  5. Семантика
  6. HTML5 и современные условия


Когда браузеры стали поддерживать JavaScript, за ним быстро закрепились две основные задачи: эффекты при наведении мышью и улучшения для веб-форм. Потом в CSS появился псевдо-класс :hover и необходимость в скриптах для многих ситуаций первого плана отпала.

Эта история постоянно повторяется. Как только определенный шаблон или задача становятся достаточно популярными, они почти непременно в конце концов упрощаются в техническом плане и делаются более доступными. Именно так в CSS3 появилось много функций для создания простых анимаций, для которых прежде требовался JavaScript.

Говоря о формах, тут возможности CSS довольно ограничены. И теперь на сцену снова выходит HTML5. Следуя тому же принципу, он вводит новые функции, которые на самом деле вовсе не новые, но сделаны проще и удобнее.

Нетрудно догадаться, что прежде они были частью отдельной спецификации WHATWG под названием Web Forms 2.0.

Текст-заглушка


Существует распространенный шаблон для оформления поисковых форм:

  1. Если поле пусто — вставить туда текст-заглушку.
  2. Когда поле в фокусе — убрать заглушку.
  3. Если пользователь оставил поле незаполненным и убрал фокус — вернуть ее.

При этом заглушка обычно выделяется немного более светлым цветом, чем вводимый в поле текст, что достигается при помощи CSS, JavaScript, или сочетания обоих.

В HTML5 все это реализуется при помощи простого параметра placeholder:

<label for="hobbies">Your hobbies</label>
<input id="hobbies" name="hobbies" type="text" placeholder="Owl stretching">

image
Так это будет выглядеть в браузере. Owl stretching — текст по умолчанию, приведенный в качестве примера.

В тех браузерах, что поддерживают этот атрибут, он работает прекрасно, но их пока не так много. Вам решать, что делать с остальными. В принципе, можно не напрягаться и не делать ничего совсем — данная функция все-таки хоть и удобна и приятна, но не жизненно важна. Но как вариант, можно разработать JavaScript-альтернативу; в этом случае сначала нужно будет убедиться, что браузер действительно не поддерживает placeholder.

Вот пример простой функции, которая проверяет поддержку определенного параметра:

function elementSupportsAttribute(element,attribute) {
	var test = document.createElement(element);
	if (attribute in test) {
		return true;
	} else {
		return false;
	}
}

Она создает «фантомный» элемент в памяти — не на самой странице, — и затем смотрит, есть ли у прототипа этого элемента свойство с тем же же названием, что и параметр, которые вы проверяете. Функция вернет либо true, либо false.

С ее помощью вы можете подсунуть альтернативный код только для тех браузеров, которые не поддерживают данную возможность HTML5:

if (!elementSupportsAttribute('input','placeholder')) {
	// Заглушка при помощи JavaScript описывается здесь.
}

Автофокус


«Привет, я функция автофокуса. Я знакома вам по таким ролям, как Google: мне повезет и Twitter: What’s happening?»

Этот шаблон очень прост и относительно легко реализуется в JavaScript. Суть его в том, что, когда страница загружена, нужно автоматически поставить фокус на определенном поле.

HTML5 позволяет использовать для этого булев параметр autofocus:

<label for="status">What's happening?</label>
<input id="status" name="status" type="text" autofocus>

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

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

Одним из преимуществ переложения роли выполнения этой функции со скриптов на разметку состоит в том, что теоретически пользователи смогут ее отключать в настройках своего браузера. Ни один браузер, впрочем, пока это не позволяет, но все еще впереди. Как бы там ни было, сейчас она может быть отключена только вместе с JavaScript вообще — не самое лучшее решение; все равно что выкалывать себе глаза, чтобы избежать слишком яркого света.

Так же как и с параметром placeholder можно проверить наличие поддержки автофокуса в браузере и, при необходимости, добавить альтернативный код на JavaScript:

if (!elementSupportsAttribute('input','autofocus')){
	document.getElementById('status').focus();
}

Параметр autofocus можно применить не только к элементам input, но к любым другим типам полей, например textarea или select. И, разумеется, только единожды на странице.

Required


JavaScript часто используется для проверки заполненности формы на стороне клиента. Снова, часть этой задачи теперь переложена на HTML5. Теперь можно указать, что определенное поле обязательно к заполнению при помощи булева параметра required.

<label for="pass">Ваш пароль</label>
<input id="pass" name="pass" type="password" required>

Теоретически, наличие незаполненного поля с этим параметром само себе должно не дать пользователю отправить данные на обработку. Но хотя пока браузеры этого и не делают, его все равно можно интегрировать для привычной обработки форм JavaScript-ом. Просто теперь вместо отбора элементов по, скажем class=«required», можно искать их по конкретно параметру required.

Автозаполнение


Современные браузеры не столько просто отображают веб-страницы, но и стараются повысить юзабилити, безопасность и удобство пользования ими. Функция автозаполнения форм — пример такого подхода. Большую часть времени она довольно полезна, но иногда может немного раздражать или даже быть потенциальным риском для безопасности. Я не против, когда браузер запоминает мои контактные данные, но я бы не хотел, чтобы он хранил логин и пароль от моего банковского счета на случай, если компьютер украдут.

HTML5 позволяет отключить автозаполнение как для отдельного поля, так и для целой формы. Параметр autocomplete — не булев, хоть и принимает всего два значения: on и off.

<form action="/selfdestruct" autocomplete="off">

По умолчанию он установлен на on, таким образом позволяя браузерам использовать автозаполнение без ограничений.

Как уже сказано, его так же можно добавить и к выборочным полям:

<input type="text" name="onetimetoken" autocomplete="off">

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

Может показаться странным, что ее включили в HTML5, учитывая, что она не особо распространена. Но она вполне оправдана, принимая во внимание угрозу для безопасности, которая может скрываться за автозаполнением; так что теперь его можно отключать при необходимости.

Datalist


Новый элемент datalist позволяет скрестить стандартный input с элементом select. Добавив параметр list, можно затем создать список предустановленных вариантов выбора:

<label for="homeworld">Ваша родная планета</label>
<input type="text" name="homeworld" id="homeworld" list="planets">

<datalist id="planets">
	<option value="Меркурий">
	<option value="Венера">
	<option value="Земля">
	<option value="Марс">
	<option value="Юпитер">
	<option value="Сатурн">
	<option value="Уран">
	<option value="Нептун">
</datalist>

Это позволяет пользователям выбрать вариант из списка или добавить свой, если его там нет. Очень удобно для ситуаций, в которых обычно требуется вставлять дополнительное поле «Другое, укажите ниже».

image
Удобный гибрид.

В случае если браузер не поддерживает datalist, такое поле будет функционировать как обычный input.

Новые input-ы


Параметр type элемента input был значительно расширен в HTML5. Здесь так много натоптанных троп, которые надо замостить, — прямо как строительство сети хайвеев на грибном месте.

Поиск

Элемент input с значением search в type работает точно так же, как и тот, что со значением text.

<label for="query">Поиск</label>
<input id="query" name="query" type="search">

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

image
Так это, например, делает Safari.

Контактные данные

Cуществуют три новых значения параметра type для разных типов контактных данных: адресов электронной почты, сайтов и номеров телефонов.

<label for="email">Email</label>
<input id="email" name="email" type="email">

<label for="website">Веб-сайт</label>
<input id="website" name="website" type="url">

<label for="phone">Телефон</label>
<input id="phone" name="phone" type="tel">

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

Safari заявляет о поддержке этих новых типов полей, но на первый взгляд, они в нем не выглядят сколько-нибудь отлично от тех, что с type=«text». Однако если вы испытаете их в Mobile Safari — том, что на мобильных устройствах Apple, — разница станет заметной. Вид экранной клавиатуры будет отличаться для разных полей:

image
Новые типы импутов в Mobile Safari.

Мелочь, а приятно.

Ползунки (те, что «слайдеры»)

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

Классический пример — ползунок. До настоящего момент его невозможно было создать без помощи JavaScript. Теперь, с HTML5, он существует как родной браузеровский input с type=«range».

<label for="amount">Сколько хотите?</label>
<input id="amount" name="amount" type="range">

image
Так выглядит input типа range в Safari и Opera.

По умолчанию, диапазон этого поля: от нуля до ста. Минимальное и максимальное значения можно задать при помощи параметров min и max соответственно.

<label for="rating">Ваша оценка</label>
<input id="rating" name="rating" type="range" min="1" max="5">

Это все хорошо работает в Safari и Opera — другие браузеры отобразят просто текстовое поле. Это не столь плохо, и мы знаем, что при желании для них всегда можно добавить альтернативную реализацию данного контрола через JavaScript, используя ту проверочную функцию, что я уже приводил выше.

Естественно, скриптовые решения потребуют больше времени на загрузку и будут менее доступны для дополнительной обработки другими средствами, чем «родные» элементы DOM. Впрочем, по непонятным причинам, тот же range в Safari в данный момент нельзя подружить с клавиатурой… Надеюсь, скоро починят.

Счетчик

Поле с типом range не отображает точное значение, выбранное пользователем, а лишь визуально представляет относительное число на ползунке. Для некоторых случаев это подходит, в других же важна точность — возможность ввести конкретное значение. Для этого есть type=«number».

<label for="amount">Сколько хотите?</label>
<input id="amount" name="amount" type="number" min="5" max="20">

Браузеры добавляют к такому полю кнопки «плюс—минус», делая его эдаким гибридом между типами text и range.

image

Дата и время

Один из наиболее популярных JavaScript-виджетов — всплывающий календарь, позволяющий выбрать нужную дату. Как на большинстве сайтов для бронирования авиабилетов, к примеру.

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

В HTML5 доступна целая горсть разных типов полей для ввода даты и времени:

date — для года, месяца и числа.
datetime — год, месяц, число, плюс часы, минуты, секунды и указание часового пояса.
datetime-local — то же самое, но без указания часового пояса.
time — часы, минуты, секунды.
month — год и месяц (без числа).

Все эти типы запишут отрезок времени в ISO формате YYYY-MM-DDThh:mm:ss.Z, где Y — год, M — месяц, D — число, h — час, m — минута, s — секунда и Z — часовой пояс. В качестве примера — дата и время окончания Первой Мировой войны, 11 часов 11 минут утра, 11-ое Ноября 1918-го года:

date: 1918-11-11
datetime: 1918-11-11T11:11:00+01
datetime-local: 1918-11-11T11:11:00
time: 11:11:00
month: 1918-11

Нет просто типа year, зато есть week — число от 1 до 53 в сочетании с годом.

Использовать все это довольно просто:

<label for="dtstart">Start date</label>
<input id="dtstart" name="dtstart" type="date">


image
Opera справляется с реализацией возможностей этих новых полей, но выглядят они в ней не сказать что очень привлекательно…

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

if (!inputSupportsType('date')) {
	// Код виджета для календаря.
}

Даже самый красиво написанный календарь такого рода на JavaScript потребует довольно большой объем кода для генерации таблицы дней и обработки событий по их выбору. Встроенная поддержка этой возможности должна работать быстрее и надежнее, не говоря о том, что устранит разнобой в оформлении.

Пипетка

Пожалуй, одним из самых смелых заменителей виджетов, представленных в HTML5, является тип поля color. Он принимает значения в виде цветовых кодов в шестнадцатеричном формате: #000000 для черного, #FFFFFF для белого, и так далее.

<label for="bgcolor">Фоновый цвет</label>
<input id="bgcolor" name="bgcolor" type="color">

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

Так что в этом случае пока следует пользоваться JavaScript-решениями, но не забывать все равно проверять встроенную поддержку — чтобы не прозевать момент, когда время таки придет.

Сделай сам


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

Хорошая новость в том, что это можно реализовать, используя параметр pattern, где можно обозначить, какой вид данных вы запрашиваете. Плохая новость в том, что вам придется использовать регулярные выражения.

<label for="zip">Почтовый индекс США</label>
<input id="zip" name="zip" pattern="[\d]{5}(-[\d]{4})">

Большую часть времени параметр pattern вам вряд ли будет нужен. Если же вы решите его задействовать — я вам сочувствую.

Взгляд в будущее


Введение новых видов веб-форм дает HTML5 заметный толчок вперед. Они перекладывают значительную часть бремени, обычно возлагаемого на JavaScript, на плечи HTML5. В данный момент мы еще на переходной стадии — не все из нововведений подерживаются браузерами, и избавиться от JavaScript совсем мы тут пока не можем. Но светлое будущее уже явно не за горами, мы видим первые его лучи и можем в них понежиться.

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

Я уверен, вы видите все преимущества встроенных в браузеры календарей и ползунков, но вижу в ваших глазах и закономерный вопрос «Можно ли к ним применить CSS-стили?»

К сожалению, на данный момент ответ скорее — «нет». Над этим работает CSS Working Group.

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

Но я хочу, чтобы вы задали себе вопрос «А нужно ли к ним применять свои стили?» Ведь многим из нас не нравится, когда горе-разработчики или -дизайнеры навязчиво заставляют нас отказывать от своих привычек и исследовать изобретенные ими интерфейсы, которые, по их мнению, лучше, стандартных (что совсем не всегда факт). Зачем же поощрать эту порочную практику введения пользователей в заблуждение?

Лично я хотел бы видеть конкуренцию браузеров за самые удобные и красивые решения для веб-форм HTML5. Такую войну браузеров я бы с удовольствием поддержал.

Окей, с формами покончено. В следующей части мы примемся за новую, аппетитную семантику HTML5.
Перевод: Jeremy Keith
Arnold Sakhnov @Olhado
карма
126,0
рейтинг 0,0
iOS
Похожие публикации
Самое читаемое Разработка

Комментарии (30)

  • +11
    Красивая статья.

    Метод elementSupportsAttribute() можно записать в 1 строку:

    return attribute in document.createElement(element);
    • 0
      Если метод, то в 3 строки:

      String.prototype.hasProperty=function(property){
      return property in document.createElement(this);
      };

      + нужно помнить, что это все же проверка свойства, а не атрибута:

      'div'.hasProperty('contenteditable'); — вернет false

      'div'.hasProperty('contentEditable'); — вернет true
  • 0
    Спасибо! Так неожиданно приятно развеяли осенний скучный день.
    • 0
      Верно, осталось дело за малым, 5 и 6 часть.
  • 0
    browser.autofocus=false; для firefox'а в about:config, по идее, и есть этот параметр, о котором написано «Ни один браузер, впрочем, пока это не позволяет, но все еще впереди.»

    Отличие типов полей вроде «tel», «serach» и т.п. (возможно ошибся в названии, ибо по памяти пишу) еще и в том, что они на выходи от дают строку без пробелов в начале и в конце (по описанию с MDN (MDC)), а «email», «url» и т.п. еще и проверяются.

    Ну и в css оно все отлично стилизуется через псевдо-классы вроде :valid и т.п.

    Вообще статья интересная, если рассматривать как вводную. А за подробностями лучше уже обращаться в спеку и маны по различным браузерам.
  • +2
    По-моему календари и ползунки в этом виде, пока, неюзабельны. А если нужно выделить диапазон времени в календаре или ограничить диапазон значений, которые может выбрать пользователь или переставить курсор на конкретную дату, время или сделать два ползунка для диапазона или диапазон не просто число, а дата. Не говоря уже о таких функция ползунка, как разный масштаб на одной линейке. Все это нужно очень часто, все это есть в javascript библиотеках, к сожалению, css, пока, не конкурент.

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

    Datalist, тоже, в этом виде подойдет только для редких случаев.

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

    Немного порадовали новые type в input, давно пора сделать веб более адаптированным для автоматического анализа, но опять же, можно было пойти намного дальше.
  • +1
    > Валидация форм на стороне клиента теперь станет намного проще — хоть и, понятное дело, всецело полагаться на нее все равно нельзя; нужно не забывать проверять данные и на стороне клиента сервера.

    так правильней?
    • 0
      Да, в переводе ошибка. Спасибо, что заметили.
  • +3
    Круто, веб-программисты получат элементы форм, которыми обычные программисты могут пользоваться уже лет 15 :)
    Все эти инструменты нужно было вводить еще в HTML 4!
    • 0
      Москва не сразу строилась… потом ее ломали и перестраивали… перетаскивали улицы и т.д… )
  • +1
    Хорошая статья и превосходные новости.

    Пара помарок:
    советую его надо использовать аккуратно
    Javascript часто используется за проверки заполненности формы
  • 0
    Очень полезные вещи. И что самое удивительное — понадобилось всего 15 лет развития интернета, чтобы эти функции наконец появились в браузерах. Аллилуя!
  • 0
    >Плохая новость в том, что вам придется использовать регулярные выражения.
    Чем? Меня радует.

    ..
    Глаз цепляется за незакрытые теги в примерах.
    • 0
      Да, несмотря на то, что автор в прошлых частях говорил, что любит синтаксис XHTML, он нигде не использует закрывающиеся одиночные теги в последующих примерах. Хорошо хоть значения параметров в кавычках ставит.
  • +1
    Так это будет выглядеть в браузере. Owl stretching ...

    Одному мне птичку жалко?
  • +1
    > Плохая новость в том, что вам придется использовать регулярные выражения.

    Почему плохая?
  • 0
    Отличная статья, спасибо. Но мне не даёт покоя один момент: автор утверждает, что все календари реализованы по-разному, и поэтому «неплохо иметь одно общее для браузера решение». Кажется, в этом месте подвох: каждый браузер начнёт отрисовывать календарь по-своему (хорошо хоть, если независимо от темы оформления браузера), и, соответственно, в разных браузерах страница будет выглядеть неодинаково.

    То же самое справедливо и для некоторых других элементов, например, поля search.

    Тут, на хабре, есть куча статей на тему стилизации файл-инпута, чтобы он одинаково выглядел во всех браузерах. Предрекаю немалое количество статей по рестайлингу html5-элементов. =)
  • 0
    Отличная статья.
    У меня есть замечание относительно Datalist
    Я два года назад, его реализовал на JS
    Но как показала практика, наши пользователи к этому еще были не готовы.
    Их вводил в ступор данный элемент.
    • 0
      >реализовал на JS. наши пользователи к этому еще были не готовы.
      Странные у вас пользователи. Наверное они никогда не пользовались подсказками в Google и Яндексе при наборе запроса. В Google это появилось шесть(!) лет назад.
  • 0
    О, про datalist не знал, классная штука! И color тоже удивил.
    Спасибо вам за эти переводы, очень помогают.

    Пара замечаний.

    К сожалению, тип URL, например, пока работает коряво. К примеру, mailto:example@adress должен быть корректным URLом, а вот та же «Опера» его не пропустит. Кроме того, желательно позволять пользователю вводить URL без указания протокола, это пока тоже работает как-то не очень.

    И реакция браузеров на ошибки так себе, некрасивая.
    Но, думаю, всё устаканится ещё.

    Теперь насчёт pattern, я считаю, что это вообще порочная идея. Не стоит мучать пользователя жёстким диктатом формата, пусть пишет как удобно, для чего у нас компьютер-то? Пусть считает, думает. Те же номера телефонов в 99% случаев можно программно определить из любого формата.

    Хотя, может иногда и к месту эта штука, тоже про неё не знал, кстати.

    А ещё совсем почти оффтопное замечание: зачем везде избыточный for в label? Label можно делать без всяких параметров, просто внутрь этого тега вкладывать input, так гораздо удобнее.

    P.S. И опечаточку нашёл. Там в конце должно быть «на стороне сервера»:
    Валидация форм на стороне клиента теперь станет намного проще — хоть и, понятное дело, всецело полагаться на нее все равно нельзя; нужно не забывать проверять данные и на стороне клиента.
  • 0
    "… светлое будущее уже явно не за горами, _МЫ_ видим первые его лучи и можем в них понежиться."
    • 0
      The xForm is dead.
      Long Live the xForm!
  • 0
    Воровство (есть подтверждение от автора книги).
  • 0
    еще можно дополнить, что type=«search» не просто рисует немного другой input, но и добавляет к нему автодополнение вашей истории поиска. Я думаю, это важно.
  • +1
    Статьи супер, только исправьте плиз:

    >когда горе-разработчики или -дизайнеры навящиво
    навязчиво
  • 0
    Господа, а как работать с ошибками при указанных «required» или регулярках в полях?
    Использую самый последний Хром, но форму он отправляет, хотя должен как-то ругнутся на пустое поле или несовпадающую регулярку.
  • 0
    Хотелось бы взглянуть на функцию «inputSupportsType()», не приведённую в статье
    • 0
      function inputSupportsType(test) {
          var input = document.createElement('input');
          input.setAttribute('type',test);
          if (input.type == 'text') {
              return false;
          } else {
              return true;
          }
          }
      

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