Xiper

Блочная верстка форм

Автор: Евгений Рыжков Дата публикации:

Задача

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

  • использование блочной верстки
  • минимум кода (минимум элементов, классов)
  • гибкость структуры
  • структурированный легко читаемый код
  • кроссбраузерность
  • семантическая разметка
  • полное разделение содержимого от оформления
  • соответствие стандартам
  • была возможность сохранить стандартный вид кнопок

Решение

Сначала отказываемся от использования универсального селектора для сброса отступов, чтобы избежать некотрых багов. Для этого используем reset.css.

Далее используем следующую HTML конструкцию:

<form action="..." method="...">
    <div>
        <label for="...">...</label>
        <input type="..." id="..." />
    </div>
    . . .
    <div>
         <label for="...">...</label>
         <input type="..." id="..." />
    </div>
    <div>
    <input type="submit" value="..." />
    </div>
</form>
  • в качестве «строк» формы используем блоки (<div>)
  • прописываем стили основным элементам формы: <div>, <label>, <input> и другим, если такие есть
  • корректируем классами оформление элементов, несовпадающих по дизайну с элементами, прописанными по умолчанию (например, если в форме несколько разных по ширине input)

Update: не забывайте, что после сдачи верстки, все еще может сильно измениться и/или доработаться (например, добавятся функции проверки корректности вводимых данных, вывод сообщений об ошибках в форме, подсказки пользователям и много чего еще может быть). Т.к. в выше предложенном примере линия формы — это div без класса, из-за наследования CSS свойств могут возникнуть проблемы с оформлением дополнительных элементов форм. Поэтому применяете "голые" только в простых формах, а в более сложных указывайте класс для <div>:

<form action="..." method="...">
    <div class="formLine">
        <label for="...">...</label>
        <input type="..." id="..." />
    </div>
    . . .
    <div class="formLine">
         <label for="...">...</label>
         <input type="..." id="..." />
    </div>
    <div class="formLine">
        <input type="submit" value="..." />
    </div>
</form>

CSS для формы:

form {
width: 300px; /* задаем ширину формы, чтобы сработал overflow */
overflow: hidden; /* обрезаем выступы за форму (в частности в ие6 неправильно расчитанный width для div) */
padding: 2px; /* небольшой отступ чтобы не обрезалась подсветка input в фокусе в Safari и Chrome */
}
form .formLine {
float: left; /* чтобы не было проблем с отступами между блоками */
width: 100%; /* чтобы блоки не встраивались в одну строку */
margin-bottom: 5px; /* расстояние между блоками */
}
form label {
float: left; /* делаем метки плавающими и фиксированной ширины чтобы выровнять их по одному уровню */
width: 60px;
text-align: right;
position: relative; /* выравниваем тексты меток и полей по одному уровню */
top: 2px; /* отступ сверху подбираем в зависимости от размера шрифта и дизайна полей */
margin-right: 5px; /* чтобы к меткам не прилипали поля */
}
form input[type=text], form input[type=password] {/* оформление для полей типа text и password */
width: 200px;
background: #fff; /* обязательно указываем цвет фона (или ставим его none), т.к. в браузере могут быть свои значения по умолчанию */
border: 1px solid #7f9db9; /* цвет бордюра */
height: 20px; /* явно задаем высоту, для кроссбраузерности */
}
form .formText {/* класс для ие6, который не понимает свойства по типам селекторов */
width: 200px;
background: #fff;
border: 1px solid #7f9db9;
height: 20px;
}
form input[type=submit] {/* оформление для кнопки submit */
margin-left: 65px;
cursor: pointer; /* меняем указатель для кнопки */
}
form .formSubmit {/* класс для ие6 */
margin-left: 65px;
cursor: pointer;
width: auto;
}
* html input {/* хак для ие6, котрый поможет ему понять типы селекторов */
z-index: expression(
runtimeStyle.zIndex = 1,
type == "text" ? (className = "formText") : 0,
type == "password" ? (className = "formText") : 0,
type == "submit" ? (className = "formSubmit") : 0
)
}

Детальней о методе можно узнать в статье «Как научить IE6 понимать в CSS типы».

Например, форма для входа на сайт:
Форма входа на сайт

<form action="php/enterToSite.php" method="post">
    <div>
        <label for="login">Логин:</label>
        <input type="text" id="login" name="login" />
    </div>
    <div>
         <label for="password">Пароль:</label>
         <input type="password" id="password" />
    </div>
    <div>
        <input type="submit" value="Войти" />
    </div>
</form>

Усложним форму:
Пример более сложной формы

HTML код:

<form action="php/register.php" method="post">
    <div>
        <input type="radio" id="mr" name="r1" /><label for="mr" class="formLabelAuto">Господин</label>
        <input type="radio" id="ms" name="r1" /><label for="ms" class="formLabelAuto">Госпожа</label>
    </div>
    <div>
        <label for="name">ФИО:</label>
        <input type="text" id="name" />
    </div>
    <div>
        <label for="email">Email:</label>
        <input type="text" id="email" />
    </div>
    <div>
        <label>Телефон:</label>+
        <input type="text" class="formCodeCountry" />
        <input type="text" class="formCodeCity" />
        <input type="text" />
    </div>
    <div>
        <label for="message">Сообщение:</label>
        <textarea id="message" cols="" rows=""></textarea>
    </div>
    <div>
         <input type="checkbox" id="dispatch" />
         <label for="dispatch" class="formLabelAuto">Подписаться на рассылку</label>
    </div>
    <div>
         <input type="submit" value="Войти" />
    </div>
</form>

CSS код:

form {
width: 500px;
overflow: hidden;
padding-top: 2px;
}
form div {
float: left;
width: 100%;
margin-bottom: 5px;
}
form label {
float: left;
width: 80px;
text-align: right;
position: relative;
top: 2px;
margin-right: 5px;
}
form input[type=text], form input[type=password] {
width: 150px;
background: #fff;
border: 1px solid #7f9db9;
height: 20px;
}
form .formText {
width: 150px;
background: #fff;
border: 1px solid #7f9db9;
height: 20px;
}
form input[type=submit] {
margin-left: 85px;
cursor: pointer;
}
form .formSubmit {
margin-left: 85px;
cursor: pointer;
width: auto;
}
form input[type=checkbox] {
border: none;
}
.formCheck {
background: none;
}
* html input {
z-index: expression(
runtimeStyle.zIndex = 1,
className == "formCodeCountry" ? (style.width = "20px") : 0,
className == "formCodeCity" ? (style.width = "30px") : 0,
type == "text" ? (className = "formText") : 0,
type == "password" ? (className = "formText") : 0,
type == "submit" ? (className = "formSubmit") : 0,
type == "checkbox" ? (className = "formCheck") : 0
)
}
form textarea {
width: 250px;
height: 100px;
}
form .formLabelAuto { /* для label рядом с radio и check */
width: auto; /* сбрасываем все, что уставили чтобы элемент вел себя как обычно */
float: none;
position: static;
}
form input.formCodeCountry { /* input с кодом страны */
width: 20px;
}
form input.formCodeCity { /* input с кодом города */
width: 30px;
}
form #mr { /* отступ для radio с Господин */
margin-left: 85px;
}
form #dispatch { /* отступ для checkbox */
margin-left: 85px;
}

Результат. В примере expression скрыт условными комментариями, чтобы CSS-код соответствовал стандартам.

Нормой в формах является пометка обязательных полей и стилизация сообщений об ошибках. Это можно сделать так:

обязательное поле помечаем звездочкой в <label>

<label for="name">ФИО:<span>*</span></label>

строка формы с ошибкой выглядит так:

<div class="formError"> <!-- добавили класс чтобы выделить label и input -->
    <label for="email">Email:<span>*</span></label>
    <input type="text" id="email" />
    <span class="formErrorMess">Введите действительный email!</span> <!-- сообщение об ошибке -->
</div>

В CSS добавляем:

form label span {
color: #ff0000; /* цвет звездочки */
}
form .formError label {
color: #ff0000; /* цвет метки при ошибке */
}
form .formError input {
border-color: #ff0000; /* цвет бордюра у поля в котором была ошибка */
}
form .formErrorMess { /* оформление сообщения об ошибке */
color: #ff0000;
display: block;
margin-left: 85px;
}

Результат.

Проверено в:

Для повышения юзабилити формы следует полям добавлять свойство maxlength, чтобы пользователь не мог ввести заведомо больше символов, чем отведено в базе данных для этого поля (согласовывается с программистами). Так же, если порядок полей может меняться, следует добавлять tabindex, для сохранения последовательного таб обхода.

Чтобы сохранить стандартный вид кнопок понадобилось использование определение типов полей в CSS (input[type=text], input[type=submit], input[type=checkbox] и др.), что повлекло использовние expression для IE6.

Недостатки метода из-за использования expression:

  • не проходит валидацию (использование условных комментариев решает эту проблему)
  • замедляет скорость загрузки страницы (только для пользователей, использующих IE6)

Если в форме используются кнопки нестандартного оформление (дизайн кнопок отличается от дизайна кнопок, которые используются по умолчанию браузерами), можно избавиться от expression:

  • задаем базовое оформление для input
  • для полей checkbox, submit, radio создаем отдельные классы (.checkbox, .submit, .radio)

Так код будет несколько «грязнее» из-за дополнительных классов, но зато без expression. Каждый выбирает сам, какой метод ему подходит больше.

По теме