Формы, таблицы и текстовый контент

1. Формы
Формы являются одним из важнейших элементов веб-сайтов и предназначены для обмена информацией между пользователем и сервером.
Благодаря формам пользователь может осуществлять поиск на странице, писать комментарии, загружать фотографии, вводить данные и многое другое.
<form>
Тег <form>
является блочным элементом, создает форму, которая служит контейнером для различных её элементов, например:
Синтаксис:
<form action="https://someserver.com/api" method="POST">
<!-- содержимое формы -->
</form>
На странице может быть несколько форм, но они не должны быть вложены друг в друга.
Существует несколько необязательных атрибутов для <form>
, на практике чаще всего применяют:
action
— адрес, который обрабатывает данные формы, если оставить пустым — форма отправится на текущую страницу;method
— метод протокола HTTP.
<input>
Тег <input>
создает различные интерактивные элементы HTML-формы, отличающиеся своим предназначением и внешним видом.
<input type="text" name="name" value="Tagree" />
Атрибуты элемента <input>
Элемент имеет большой список атрибутов, определяющих его поведение. Разберём основные, с прочими необходимо будет ознакомиться самостоятельно.
name
— имя поля, отправляется вместе с его значением;value
— значение поля;type
— основной атрибут, определяющий тип и поведение элемента;required
— устанавливает поле обязательным для заполнения перед отправкой формы;readonly
— значение поля не может быть изменено пользователем;disabled
— отключает поле, его значение не передаётся с формой;placeholder
— текстовая подсказка внутри поля, исчезает при наборе текста;autofocus
— устанавливает фокус на поле после загрузки страницы.maxlength
— устанавливает максимальное число введённых символов;minlength
— устанавливает минимальное число введённых символов;min
— минимальное значение для ввода числа или даты;max
— максимальное значение для ввода числа или даты.
В зависимости от атрибута type
элемент <input>
может иметь описанные далее представления.
Основные текстовые поля:
Type | Описание | Внешний вид |
---|---|---|
text | однострочное текстовое поле | |
email | поле для ввода адреса электронной почты, должно содержать действительный адрес или пустую строку. | |
password | поле для ввода пароля, вводимые символы отображаются “звездочками” |
Данные типы имеют наиболее широкое применение.
Прочие текстовые поля:
Type | Описание | Внешний вид |
---|---|---|
number | поле для ввода чисел с плавающей точкой (тип float ) | |
search | поле для ввода строки поиска | |
tel | поле для ввода номера телефона | |
url | поле для ввода web-адреса, должно содержать допустимый абсолютный URL или пустую строку |
Данные типы применяются реже, имеют различное поведение, внешний вид и элементы управления в разных браузерах. Могут быть легко заменены полем ввода типа text
, а валидация (проверка верного значения) и элементы управления для таких полей могут быть выполнены с помощью дополнительной разметки и JavaScript.
Чекбоксы, радио-кнопки, диапазон:
Тип | Описание | Внешний вид |
---|---|---|
checkbox | чекбоксы позволяют выбрать один или несколько предложенных вариантов. За наличие флажка отвечает дополнительный атрибут checked | Вариант 1 Вариант 2 |
radio | радиокнопки используются для выбора одного варианта из нескольких предложенных, должны иметь одинаковое значение атрибута name и разные значения value , выбранное значение определяется наличием атрибута checked | Вариант 1 Вариант 2 |
range | ползунок для ввода чисел в указанном диапазоне с помощью атрибутов min , max , step . |
Время и дата
Тип | Описание | Внешний вид |
---|---|---|
date | поле для ввода календарной даты(гггг‑мм‑дд) | |
time | поле для ввода времени(чч:мм) | |
datetime-local | поле для ввода даты и местного времени(гггг‑мм‑ддTчч:мм) | |
month | поле для ввода месяца и года(гггг‑мм) | |
week | выбор недели(гггг‑W00) |
Данные поля имеют различное поведение, внешний вид и элементы управления в разных браузерах. Часто вместо них используют различные JavaScript-плагины в сочетании с полем ввода типа text
.
Кнопки
Тип | Описание | Внешний вид |
---|---|---|
button | кнопка без предопределённого поведения, значение атрибута value выводится как текст внутри данной кнопки | |
submit | кнопка для отправки данных формы на сервер , значение атрибута value выводится как текст, а при наличии атрибута name оно будет отправлено вместе с данными формы | |
image | графическая кнопка для отправки данных формы на сервер, изображение задаётся атрибутом src | |
reset | кнопка сброса данных формы в первоначальное состояние |
Прочее
Тип | Описание | Внешний вид |
---|---|---|
file | элемент, позволяющий пользователю прикрепить файл; разрешённые типы файлов задаются с помощью дополнительного атрибута accept ;атрибут multiple позволяет прикрепить несколько файлов. | |
color | элемент для выбора цвета в шестнадцатеричном формате #rrggbb | |
hidden | скрытое поле, которое не отображается, но его значение будет отправлено на сервер |
<textarea>
Teг <textarea>
— это многострочный элемент формы, в котором, в отличие от <input>
, допустимо делать переносы строк, сохраняющиеся при отправке данных не сервер.
<textarea name="text" rows="3">
Многострочное поле ввода
</textarea>
Основные атрибуты:
name
— имя поля, отправляется вместе с его значением;required
— устанавливает поле обязательным для заполнения перед отправкой формы;readonly
— значение поля не может быть изменено пользователем;disabled
— отключает поле, его значение не передаётся с формой;placeholder
— текстовая подсказка внутри поля, исчезает при наборе текста;autofocus
— устанавливает фокус на поле после загрузки страницы.maxlength
— устанавливает максимальное число введённых символов;minlength
— устанавливает минимальное число введённых символов;cols
— ширина поля в текстовых символах (по умолчанию 20), если не задана в CSS.rows
— высота поля в строках текста (по умолчанию 2), если не задана в CSS.
<select>
Тег <select>
создаёт элемент в виде раскрывающегося списка опций с одним или множественным выбором.
<select name="options">
<option value="1" selected>Опция 1</option>
<option value="2" disabled>Опция 2</option>
<option value="3">Опция 3</option>
</select>
Атрибуты:
name
— имя поля, отправляется вместе с его значением;required
— устанавливает поле обязательным для заполнения перед отправкой формы;disabled
— отключает поле, его значение не передаётся с формой;multiple
— позволяет множественный выбор опций;autofocus
— устанавливает фокус на поле после загрузки страницы;size
— количество отображаемых строк списка, по умолчанию — 0.
Каждый пункт создается с помощью тега <option>
.
Атрибуты <option>
:
value
— значение опции, которое будет отправлено на сервер;selected
— выбранный пункт из списка;disabled
— заблокированный, недоступный элемент списка;label
— отображаемый текст, описание опции, если атрибут не указан, то его значение совпадает с текстовым содержанием данного элемента;
Атрибут form
Если поле находится вне формы, оно может быть связано с данной формой с помощью атрибута form
, значением которого должен быть указан идентификатор id
этой формы.
<form id="some_form">
</form>
<input form="some_form">
<textarea form="some_form"></textarea>
<select form="some_form"></select>
<label>
Тег <label>
устанавливает связь между собой и определённым элементом формы.
При использовании <label>
его содержимое становится интерактивным точно так же, как и элемент формы, к которому он привязан (например, радио-кнопка или чекбокс). Это хорошая практика применения, поскольку область нажатия становится больше, что упрощает работу пользователя.
Существует два варианта связывания элемента формы и <label>
:
1. Для элемента формы указывается идентификатор id
, и то же самое значение задаётся в качестве атрибута for
элементу <label>
.
<input id="some_id">
<label for="some_id">
Метка для поля
</label>
2. Элемент формы помещается внутри <label>
.
<label>
Метка для поля
<input>
</label>
<fieldset>
Тег <fieldset>
используется для группировки различных элементов формы. При большом количестве данных такая группировка облегчает работу с формами. По умолчанию отображаются в виде рамки.
Атрибуты:
disabled
— доступ к полям группы заблокирован;form
— cвязывает группу с формой по её идентификаторуid
, даже если группа находится вне данной формы.
<legend>
Тег <legend>
применяется для создания заголовка группы элементов формы <fieldset>
.
<button>
Тег <button> создаёт кликабельную кнопку, которая может быть использована в формах или в любом другом месте документа при необходимости.
Атрибуты:
autofocus
— установка фокуса на кнопку после загрузки страницы;disabled
— блокирует взаимодействие с кнопкой;form
— связывает между собой форму и кнопку;formaction
— задаёт адрес, на который пересылаются данные формы при нажатии на кнопку;formenctype
— способ кодирования данных формы;formmethod
— указывает метод пересылки данных формы;formnovalidate
— отменяет проверку формы на корректность;formtarget
— открывает результат отправки формы в новом окне или фрейме;name
— определяет уникальное имя кнопки;type
— тип кнопки, определяющий её функциональность;value
— значение кнопки, которое будет отправлено на сервер или прочитано с помощью скриптов.
Особое внимание уделим атрибуту type
, так как именно он определяет поведение кнопки в форме.
Значения type
:
button
— стандартная кнопка без предопределённого поведения;submit
— кнопка для отправки данных формы на сервер, является значением по умолчанию;reset
— кнопка очищает набранные пользователем данные в форме и возвращает в первоначальное состояние;
Кнопки в форме
Из представленной выше информации становится ясно, что кнопки можно создать двумя способами:
1. с помощью элемента <input>
<input type="button" value="Текст">
Важные правила:
<input>
нельзя вкладывать внутрь ссылки<a>
;<input>
нельзя вкладывать внутрь кнопки<button>
.
2. с помощью элемента <button>
По своей функциональности напоминает работу <input>
(первый способ). Однако имеет ряд преимуществ, например, возможность размещать внутри себя другие HTML-элементы, так как является парным тегом.
Важные правила:
<button>
не может быть вложен в другой<button>
;<button>
нельзя вкладывать внутрь ссылки<a>
.
Полезные советы по созданию форм
1. Для отправки данных на сервер необходимо прописать значение атрибута name
для каждого элемента формы.
Это важно и для браузера (так как он считывает, какие имена необходимо дать каждой части данных), и для сервера (ведь он получает данные, обращаясь по заданным именам). Данные формы отправляются в виде пары имя/значение.
2. Если элементы формы находятся за пределами формы, отправка введенных данных на сервер не произойдет.
Для того, чтобы данные элементов формы, которые размещены за пределами <form>
были отправлены на сервер, необходимо прописать таким элементам атрибут form
со значением, которое будет соответствовать значению атрибута id
формы <form>
.
<input type="submit" form="some_form">
<form id="some_form">
<input type="text" name="name">
</form>
К данной практике стоит прибегать в том случае, если элементы формы в макете дизайна находятся далеко друг от друга.
3. При создании форм старайтесь подписывать названия полей ввода с помощью <label>
, а также указывайте placeholder (подсказка внутри текстового поля). Всё это поможет сделать интерфейс понятным и удобным для любого пользователя.
2. Вёрстка элементов формы
Рассмотрим данную тему на примере формы учебного проекта.

Текстовые поля
Общие свойства
Сперва добавим некоторые общие свойства для полей в common.less, стандартизируя поведение в разных браузерах:
input,
textarea,
select {
box-shadow: none;
outline: none;
color: @black;
font-family: @font1;
}
textarea {
resize: none;
}
CSS-свойство outline
создаёт контурную линию вокруг элемента, не занимает место и не влияет на блочную модель. По умолчанию элементы, с которыми можно взаимодействовать, при получении фокуса отображают контур. Таким образом активное поле оказывается явно выделенным. К сожалению разные браузеры могут отображать контур с разным стилистическим оформлением, а старые браузеры не поддерживают закругление углов для этого свойства.
В дизайне нашего учебного проекта отсутствует выделение активного поля, поэтому мы просто отключим данное свойство. Отметим лишь, что схожего поведения при фокусе на элементе можно также добиться с помощью CSS-свойства box-shadow
, добавляющему элементу тень и псевдокласса :focus
, который активируется при клике мышью пользователем или при выборе элемента с использованием клавиши «tab» на клавиатуре.
Свойство resize
в значении none
запрещает изменение размера поля пользователем.
Подсказки для текстовых полей
Текстовые поля могут иметь подсказки, которые по умолчанию имеют светло-серый цвет и исчезают при начале ввода. Задаются они с помощью атрибута placeholder
:
<input type="text" placeholder="Подсказка для поля">
По умолчанию подсказка не исчезает при клике по полю и получения им фокуса. Очень часто это путает людей, и вместо того, чтобы начать набирать текст, они пытаются стереть подсказку.
С помощью псевдоэлемента ::placeholder можно задать подсказкам цвета и переопределить их поведение следующим образром:
input,
textarea {
&::placeholder {
color: #6C6C6C;
}
}
input:focus,
textarea:focus {
&::placeholder {
color: transparent
}
}
Однострочные и многострочные поля
Создадим новый БЭМ-блок .field
, который будет содержать в себе свойства различных полей, подписей к ним, а в дальнейшем — и сообщений об ошибках.
<!--Разметка однострочного поля ввода (для <input>)-->
<label class="field">
<span class="field__label">Имя*</span>
<input class="field__input" type="text" placeholder="Имя" name="name" required>
</label>
<!--Разметка многострочного поля ввода (для <textarea>)-->
<label class="field">
<span class="field__title">Есть пожелания? Напишите нам:</span>
<textarea class="field__textarea" name="Пожелания"></textarea>
</label>
.field {
display: flex;
flex-direction: column;
&__input,
&__textarea {
box-sizing: border-box;
display: block;
width: 100%;
border: none;
border-radius: 5px;
background-color: @white;
font-size: 16px;
line-height: 1.375;
}
}
Свойства для однострочных полей ввода:
.field {
&__input {
height: 55px;
padding: 0 20px;
}
}
Свойства для многострочных полей ввода:
.field {
&__textarea {
height: 150px;
padding: 20px;
}
}
В нашем дизайне два вида подписей к полям, стилизуем оба:
.field {
&__title {
display: block;
margin: 0 0 10px;
color: @black;
font-weight: 700;
font-size: 18px;
line-height: 25px;
}
&__label {
display: block;
margin-bottom: 5px;
font-size: 16px;
line-height: 1.3;
color: @black;
}
}
Результат:
Select
Стандартный селект плохо поддаётся стилизации, в дальнейшем мы используем для этого js-плагин, а пока сделаем то, что можем на данный момент.
<label class="field">
<span class="field__title">Планируемое количество посетителей:</span>
<select
class="field__select"
name="amount"
>
<option value="20">до 20 человек</option>
<option value="100">от 20 до 100 человек</option>
<option value="500">от 100 до 500 человек</option>
<option value="1000">более 500 человек</option>
</select>
</label>
.field {
&__select {
box-sizing: border-box;
display: block;
width: 100%;
height: 55px;
padding: 0 20px;
border: none;
border-radius: 5px;
background-color: @white;
font-size: 16px;
line-height: 1.375;
}
}
Результат:
Радиокнопки
Кастомный вид радиокнопки достигается за счёт скрытия стандартного элемента и создания «поддельного» с помощью разметки и CSS:
Создаем разметку
<div class="radio">
<label class="radio__item">
<input class="radio__input" type="radio" name="format" value="seminar" checked>
<span class="radio__mark"></span>
<span class="radio__label">Мастер-класс/семинар</span>
</label>
<label class="radio__item">
<input class="radio__input" type="radio" name="format" value="concert">
<span class="radio__mark"></span>
<span class="radio__label">Концерт/выступление</span>
</label>
</div>
Радиокнопки всегда должны содержать как минимум два элемента, иначе выбор невозможно будет отменить.
Стилизуем <label>
.radio {
display: flex;
flex-direction: column;
align-items: flex-start;
&__item {
box-sizing: border-box;
position: relative;
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: 15px;
min-height: 23px;
padding-left: 23px;
color: @black;
cursor: pointer;
&:last-child {
margin-bottom: 0;
}
}
}
Ширина и высота кастомной радиокнопки без подписи составляет 23px
, поэтому зададим такое значение для минимальной высоты элемента (подпись может быть и многострочной) и внутренний отступ слева, в котором будет находиться элемент, отвечающий за визуальную составляющую.
Скрываем стандартный элемент <input>
Прописывать { display: none }
полю ввода некорректно, так как некоторые браузеры могут не отправить значение такого поля, а отдельные JavaScript плагины валидации пропускают проверку скрытых полей. Скроем элемент лишь визуально и вырвем его из потока.
Чтобы гарантированно и кроссбраузерно визуально скрыть элемент, добавим в файл mixins.less
новый миксин:
.is-hidden {
position: absolute !important;
width: 0 !important;
height: 0 !important;
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
clip: rect(0 0 0 0) !important;
clip-path: inset(100%) !important;
white-space: nowrap !important;
overflow: hidden !important;
visibility: hidden !important;
pointer-events: none !important;
}
Изучите все новые для вас CSS-свойства самостоятельно. Теперь скроем стандартную радиокнопку:
.radio {
&__input {
.is-hidden();
}
}
Создаем «поддельную» радиокнопку
.radio {
&__mark {
box-sizing: border-box;
display: block;
position: absolute;
left: 0;
top: 0;
width: 23px;
height: 23px;
border: 2px solid @black;
border-radius: 50%;
padding: 3px;
background-clip: content-box;
background-color: transparent;
transition: background-color 0.2s;
}
}
Благодаря свойству background-clip
и заданному значению content-box
фон радиокнопки будет окрашивать только внутренне пространство, не включая внутренние отступы.
По умолчанию фон прозрачный, а в состоянии checked
— чёрный:
.radio {
&__input {
.is-hidden();
&:checked {
&~.radio__mark {
background-color: @black;
}
}
}
}
Стилизация подписи:
.radio {
&__label {
margin-left: 20px;
font-weight: 400;
font-size: 16px;
line-height: 22px;
}
}
Результат:
Чекбокс
Cтилизация чекбоксов осуществляется аналогично радиокнопкам. Отличие здесь заключается в том, что каждый чекбокс полностью независим от других и может иметь два состояния: отмечен, или нет.
Создаем разметку
<label class="check">
<input
type="checkbox"
name="agree"
class="check__input"
required
checked
/>
<span class="check__mark"></span>
<span class="check__label check__label--s">
Я соглашаюсь с пользовательским соглашением и с политикой
использования персональных данных
</span>
</label>
Стилизуем <label>
.check {
box-sizing: border-box;
position: relative;
display: inline-flex;
flex-direction: column;
align-items: flex-start;
min-height: 24px;
padding-top: 2px;
padding-left: 24px;
color: @black;
cursor: pointer;
}
Скрываем стандартный элемент <input>
.check {
&__input {
.is-hidden();
}
}
Создаем «поддельный» чекбокс
.check {
&__mark {
box-sizing: border-box;
display: block;
position: absolute;
left: 0;
top: 0;
width: 24px;
height: 24px;
border: 1px solid @black;
}
}
Стилизуем «поддельный» чекбокс в состоянии checked
.check {
&__input {
.is-hidden();
&:checked {
& ~ .check__mark {
background-color: @black;
&::after {
content: "";
display: block;
position: absolute;
left: 7px;
top: 2px;
width: 6px;
height: 12px;
border-bottom: 2px solid @white;
border-right: 2px solid @white;
transform: rotate(45deg);
}
}
}
}
}
Галочку мы создали с помощью повёрнутого на 45 градусов псевдоэлемента, двум сторонам которого заданы бордюры (CSS-свойство border
).
Стилизация подписи
.check {
&__label {
margin-left: 15px;
font-weight: 300;
font-size: 16px;
line-height: 22px;
&--s {
font-size: 14px;
line-height: 19px;
}
}
}
Подписи чекбоксов в разных формах имеют отличающиеся размеры шрифта, поэтому мы задали модификатор.
Результат:
3. Вёрстка форм макета
Попап с формой заявки мероприятия
Благодаря полученным знаниям о создании формы и её элементах, мы можем сверстать попап с формой заявки для учебного проекта.
Сперва создадим новый файл event-pp.html
в каталоге src/html/blocks
учебного проекта и подключим его на страницах index.html
и events.html
, сделать это лучше непосредственно в <body>
.
<!DOCTYPE html>
<html lang="ru">
@@include('blocks/head.html')
<body class="body">
@@include('blocks/page-header.html')
<main class="main"></main>
@@include('blocks/page-footer.html')
@@include('blocks/event-pp.html')
</body>
</html>
Попапы на сайте могут использоваться для разных целей, поэтому создадим новый БЭМ-блок и пропишем соответствующие стили. Старайтесь избегать в названиях классов такие наименования как «popup», «add», и подобные, так как такие элементы могут оказаться заблокированы блокировщиками рекламы.
<div class="pp" id="eventPP">
<div class="pp__wrapper">
<div class="pp__sticky-close">
<button class="pp__x-btn x-btn">
<svg class="x-btn__icon" width="12" height="12">
<use xlink:href="assets/icons/symbols.svg#x"></use>
</svg>
</button>
</div>
<div class="pp__container">
<h2 class="pp__title">Заполните форму<br />и мы подберем площадку</h2>
<form class="pp__form form">
<!-- Содержимое формы -->
</form>
</div>
</div>
</div>
Круглую кнопку закрытия .x-btn
также выделим в отдельный БЭМ-блок.
Наш попап по молчанию должен быть скрыт, поэтому прежде чем приступить к его стилизации, создайте новый миксин .show-event-popup
, который необходимо добавить в качестве класса тегу <html>
. Пока сделаем это вручную, а далее обработка будет осуществляться с помощью JavaScript.
<!DOCTYPE html>
<html lang="ru" class="show-event-popup">
<!-- Содержимое страницы -->
</html>
.show-event-popup {
body {
overflow: hidden;
}
#eventPP {
display: flex;
}
}
Мы задаем для body CSS-свойство overflow
в значении hidden
для того, чтобы предотвратить прокрутку страницы, когда наш попап открыт.
CSS-правила для попапа:
.pp {
box-sizing: border-box;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 90px 95px 50px;
background-color: rgba(28, 27, 27, 0.4);
backdrop-filter: blur(50px);
overflow-y: auto;
z-index: 110;
display: none;
&__wrapper {
box-sizing: border-box;
position: relative;
display: flex;
flex-direction: column;
width: 100%;
max-width: 1210px;
margin: auto;
background-color: @gray;
background-image: url(../assets/images/noise.png);
background-position: 0 0;
background-size: auto;
background-repeat: repeat;
}
&__container {
box-sizing: border-box;
width: 100%;
max-width: 950px;
margin: 0 auto;
padding: 0 40px 40px;
}
}
Итак, наш попап по умолчанию скрыт, имеет фиксированное позиционирование, вертикальную прокрутку, внутренние отступы и большой z-index
, позволяющий ему перекрыть все прочие элементы.
Здесь мы снова сталкиваемся с плохоподдерживаемым CSS-свойством backdrop-filter
. В этот раз решите проблему самостоятельно.
БЭМ-элемент .pp__wrapper
благодаря Flexbox и автоматическим отступам выравнивается посередине экрана.
Заголовок выставим с помощью отрицательных внешних отступов, а круглую кнопку с крестиком обернём дополнительной обёрткой с нулевыми размерами, чтобы она не влияла на поток, и зададим липкое позиционирование sticky
, чтобы кнопка прокручивалась вместе с содержимым попапа:
.pp {
&__sticky-close {
position: sticky;
top: 0;
align-self: flex-end;
width: 0;
height: 0;
}
&__x-btn {
position: absolute;
top: -30px;
right: -30px;
}
&__title {
box-sizing: border-box;
display: flex;
align-items: center;
margin: -40px 0 70px -85px;
padding: 10px 85px;
width: 595px;
min-height: 80px;
background-color: @black;
text-transform: uppercase;
font-weight: 400;
font-family: @font2;
font-size: 22px;
line-height: 1.36;
color: @white;
letter-spacing: 0.02em;
z-index: 1;
}
}
Как стилизовать все элементы формы мы уже знаем, попробуйте задать разметку и стили самостоятельно. Всем обязательным полям задайте атрибут required
. Когда форма будет готова, уберите миксин с тега <html>
, чтобы скрыть её.
Получиться должно примерно так:
Напоминаем, разметка и стили в песочнице не имеют полного соответствия с требуемыми в силу технических ограничений. Селект «Планируемое количество посетителей» и поле «Дата проведения» в дальнейшем кастомизируем с помощью JS-плагинов.
Форма бронирования стола
Мы уже задали основную структуру данной формы на одном из предыдущих уроков, подробно останавливаться не будем, но отметим некоторые моменты.
Список чекбоксов
Не используйте БЭМ-блок .form
для выстраивания элементов данной формы, в этом нет необходимости, форма слишком сильно отличается своим содержанием от стандартной.
Так, список чекбоксов может выглядеть следующим образом:
<form class="reserve">
<div class="reserve__checks">
<h4 class="reserve__section-title">
Забронировать столик
</h4>
<label class="reserve__check check check--red">
<input
type="checkbox"
name="table_1"
class="check__input"
/>
<span class="check__mark"></span>
<span class="check__label">1 стол</span>
</label>
<label class="reserve__check check">
<input
type="checkbox"
name="table_2"
class="check__input"
/>
<span class="check__mark"></span>
<span class="check__label">2 стол</span>
</label>
<!-- Ещё чекбоксы -->
<label class="reserve__check check check--disabled">
<input
type="checkbox"
name="table_5"
class="check__input"
disabled
/>
<span class="check__mark"></span>
<span class="check__label">5 стол </span>
</label>
<!-- Оставшиеся чекбоксы -->
</div>
<!-- Прочие элементы формы -->
</form>
У нас появилось два новых типа чекбоксов: красного цвета и отключенный — его сделаем полупрозрачным. Допишем соответствующие стили:
.check {
&--red {
color: @red;
.check__mark {
border-color: @red;
}
.check__input {
&:checked {
& ~ .check__mark {
background-color: @red;
}
}
}
}
&--disabled {
pointer-events: none;
opacity: 0.5;
}
}
Схема столов
Скачайте по ссылке файл «карта_заведения.svg
«, не экспортируйте схему столов непосредственно из проекта в Figma, мы вручную внесли некоторые правки и подготовили разметку схемы за вас. Откройте файл текстовым редактором и вставьте код непосредственно в вашу разметку.
<form class="reserve">
<!-- Прочие элементы формы -->
<div class="reserve__scheme">
<div class="reserve__scheme-container">
<h4 class="reserve__scheme-title">Сцена</h4>
<div class="reserve__scheme-wrapper">
<svg
class="reserve__scene scene"
width="780"
height="399"
viewBox="0 0 780 399"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<!-- Содержимое svg -->
</svg>
</div>
</div>
</div>
<!-- Прочие элементы формы -->
</form>
Гибкие размеры схемы зададим по аналогии с тем, как мы делали в карточках листингов для изображений, — с помощью псевдоэлемента.
.reserve {
&__scheme-wrapper {
position: relative;
width: 100%;
&::after {
content: "";
display: block;
width: 100%;
padding-top: 51.15384%;
}
}
&__scene {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
Блок с ценой и количеством билетов
Данный блок никакой сложности не представляет, но на данном примере разберём ещё один вариант использования псевдоэлементов.
<form class="reserve">
<!-- Прочие элементы формы -->
<div class="reserve__order">
<h4 class="reserve__section-title">Ваши пригласительные билеты</h4>
<div class="reserve__tickets-list">
<div class="reserve__tickets">
<div class="reserve__qty" data-caption="шт." data-price="1400">0</div>
<div class="reserve__sum" data-currency="₽">0</div>
</div>
<div class="reserve__tickets">
<div class="reserve__qty" data-caption="шт." data-price="1250">0</div>
<div class="reserve__sum" data-currency="₽">0</div>
</div>
</div>
<div class="reserve__total" data-caption="Сумма" data-currency="₽">0</div>
<button type="submit" class="btn btn--red reserve__submit">
Купить билеты
</button>
</div>
<!-- Прочие элементы формы -->
</form>
Все подписи к значениям строк мы вынесли в data-атрибуты, которые мы можем отобразить с помощью псевдоэлемента и CSS-свойства content
со значением attr(attribute name)
.
.reserve {
&__tickets {
display: flex;
justify-content: space-between;
align-items: baseline;
}
&__qty {
&::after {
content: " " attr(data-caption) " | " attr(data-price);
}
}
&__sum {
&::after {
content: attr(data-currency);
margin-left: 4px;
font-size: 0.95em;
}
}
&__total {
&::before {
content: attr(data-caption);
margin-right: 30px;
}
&::after {
content: attr(data-currency);
margin-left: 4px;
font-size: 0.95em;
}
}
}
Такой подход позволяет избежать лишней разметки, и в дальнейшем упростит работу с формой, когда мы будем рассчитывать конечную стоимость билетов с помощью JavaScript, так как в соответствующие элементы нам нужно будет вставить только результирующие цифры и не думать о подписях к ним.
Недостающие CSS-свойства пропишите самостоятельно.
Легенда
Данный блок создайте полностью самостоятельно по аналогии с предыдущим.
4. Таблицы
Таблицы, представляют собой набор строк и столбцов, на пересечении которых располагаются ячейки.
Особенностью HTML-таблиц является то, что они создаются по строкам.
<table>
Данный элемент служит контейнером для строк <tr>
и ячеек <td>
. Все элементы должны строго находиться внутри <table>
.
Синтаксис:
<table>
<!-- Содержимое таблицы -->
</table>
Элементами для построения таблицы являются:
Вложенность таблиц возможна, но это не рекомендуется делать, так как усложняет разметку и снижает доступность страницы (например, для работы скринридеров).
<caption>
Тег <caption>
является заголовком таблицы, это необязательный элемент. При использовании он всегда должен быть первым вложенным элементом тега <table>
.
Синтаксис:
<table>
<caption>
Заголовок
</caption>
<!-- Содержимое таблицы -->
</table>
<thead>
Тег <thead>
(table head) задаёт шапку таблицы, может включать в себя одну или несколько строк. Не является обязательным элементом. В одной таблице допускается только один элемент <thead>
, который располагается первым вложенным элементом тега <table>
или сразу после тега <caption>
.
Для поддержания семантики, ячейки внутри <thead>
следует задавать тегом <th>
.
Синтаксис:
<table>
<caption>
Заголовок таблицы
</caption>
<thead>
<tr>
<th>
<!-- Содержимое ячейки -->
</th>
</tr>
</thead>
<!-- Прочее содержимое таблицы -->
</table>
<tbody>
Тело таблицы <tbody>
может содержать в себе одну или несколько строк. Использование данного тега помогает структурировать блоки.
Особенности:
- тег не является обязательным;
- может быть использован несколько раз в пределах одной таблицы;
- если в таблице используется
<thead>
,<tbody>
должно идти после; - в случае использования
<tbody>
таблица не может в качестве прямых потомков содержать строки , все они должны находиться в шапке, теле, или подвале таблицы.
Синтаксис:
<table>
<tbody>
<tr>
<th>
Заголовок
</th>
<td>
Ячейка
</td>
</tr>
</tbody>
</table>
<tfoot>
Подвал таблицы <tfoot>
(table foot) служит для объединения строк и ячеек, суммирующих таблицу. В таблице можно использовать только один элемент <tfoot>
, который должен идти последним.
Элементы <thead>
, <tfoot>
и <tbody>
должны содержать одинаковое число колонок и по меньшей мере одну строку.
Синтаксис:
<table>
<caption></caption>
<thead></thead>
<tbody></tbody>
<tfoot></tfoot>
</table>
<tr>
Строка таблицы, <tr>
(table row), может содержать в себе обычные ячейки <td>
или заголовки <th>
.
Синтаксис:
<table>
<tr>
<th>
Ячейка 1, заголовок строки
</th>
<td>
Ячейка 2
</td>
<td>
Ячейка 3
</td>
</tr>
</table>
<th>
Ячейка таблицы <th>
используется для заголовков строки или столбца (table header cell).
Синтаксис:
<table>
<tr>
<th>
Ячейка таблицы, являющаяся заголовком
</th>
</tr>
</table>
Атрибуты:
colspan
— объединяет горизонтальные ячейки;rowspan
— объединяет вертикальные ячейки;abbr
— краткое описание содержимого ячейки, может использоваться в речевых браузерах;headers
— позволяет связать ячейки таблицы с заголовками<th>
, имеющим соответствующий атрибутid
, может использоваться в речевых браузерах;scope
— позволяет связать ячейки таблицы, строки, колонки и группы с заголовками<th>
, может использоваться в речевых браузерах.
<td>
Ячейка таблицы <td>
(table data cell) может содержать любую информацию.
Синтаксис:
<table>
<tr>
<td>
Ячейка 1
</td>
<td>
Ячейка 2
</td>
</tr>
</table>
Атрибуты:
colspan
— объединяет горизонтальные ячейки;rowspan
— объединяет вертикальные ячейки.headers
— позволяет связать ячейки таблицы с заголовками<th>
, имеющим соответствующий атрибутid
, может использоваться в речевых браузерах;
<col>
и <colgroup>
Теги <col>
и <colgroup>
служат для объединения общих свойств колонок таблицы и оптимизируют разметку путём сокращения повторяющихся атрибутов ячеек указанных колонок, не являются обязательным.
На данный момент возможно объединить CSS-свойства, отвечающие за ширину и фон ячеек. Для других CSS-свойств эффект будет отсутствовать.
Тег <colgroup>
элемент может быть одиночным тегом, или же парным и содержать в себе один или несколько тегов <col>
, объединяя таким образом колонки в группы.
Атрибуты:
- span — количество колонок, к которым следует применяться определенные характеристики. Значением является целое положительное число, если оно не прописано, то по умолчанию равно 1. Если
<colgroup>
содержит внутри себя<col
> — данный атрибут указывается только для<col>
.
Данные теги могут располагаться в начале таблицы перед <thead>
, но после <caption>
.
<table>
<caption>Заголовок таблицы</caption>
<colgroup span="2">
<thead></thead>
<tbody></tbody>
<tfoot></tfoot>
</table>
Примеры:
Объединение ячеек
Объединение ячеек (как по горизонтали, так и по вертикали) осуществляется благодаря атрибутам colspan
и rowspan
, при этом «поглощаемые» ячейки задавать в разметке уже не нужно.
Атрибут colspan
объединяет ячейки по горизонтали (ячейки одной строки), значением является количество столбцов, которые пересекает ячейка.
Атрибут rowspan
объединяет ячейки по вертикали (ячейки разных строк), значением является количество строк, которые проходит ячейка.
Пример:
Стилизация таблицы
1. По умолчанию таблицы и ячейки не имеют границ и фона, стоит задать какое-либо из этих свойств самостоятельно, чтобы обозначить отдельные ячейки.
table,
td {
border: 1px solid #000000;
}
2. По умолчанию между границами ячеек и границами самой таблицы имеется небольшой отступ. Для того, чтобы «схлопнуть» границы, нужно прописать CSS-свойство border-collapse
со значением collapse
. Для возвращения в исходное состояние используется значение separate
.
3. Выравнивание контента по вертикали в ячейках осуществляется с помощью CSS-свойства vertical-align
, которое принимает значения:
baseline
— выравнивание по базовой линии шрифта;top
— выравнивание по верхнему краю ячейки;middle
— выравнивание по центру;bottom
— выравнивание по нижнему краю ячейки.
4. Ячейки в таблице по умолчанию имеют свойство { display: table-cell
}, менять его для позиционирования содержимого нельзя, так как это сломает работу всей таблицы.
Чтобы, к примеру, воспользоваться моделью Flexbox для содержимого ячейки, его необходимо обернуть в дополнительную обертку внутри ячейки.
5. Задавать свойство width
ячейкам таблицы на практике не рекомендуется, так как таблица самостоятельно выравнивает ширину своих ячеек в зависимости от содержимого контента в них.
5. Таблица — вёрстка макета
На макете листинга мероприятий имеется таблица с тарифами. Полученные знания позволяют без каких либо проблем её сверстать. Подробно разбирать не будем, пример в песочнице представлен ниже.
6. Текстовый контент
Часть контента на страницах сайта задается администратором или контент-менеджером с помощью текстового редактора панели администрирования. Чтобы такой контент не «выбивался» из общего дизайна сайта, всем элементам, доступным из редактора, следует прописать собственные CSS-правила.

На макете страницы, содержащей редактируемый контент, могут отсутствовать все требующие стилизации элементы, но, так как за содержание подобных страниц разработчик отвечать не может, следует самостоятельно предусмотреть все возможные сценарии.
Создадим стандартную страницу для текстового контента default.html
, содержащую минимальный набор необходимых элементов, а также отдельный CSS-блок .content
, в котором будут прописаны все правила оформления.
Текстовый редактор обычно включает в себя:
- заголовки;
- абзацы текста;
- списки;
- ссылки;
- изображения;
- цитаты.
- жирный текст;
- курсив;
<!DOCTYPE html>
<html lang="ru">
@@include('blocks/head.html')
<body class="body">
@@include('blocks/page-header.html')
<main class="main">
<article class="article">
<div class="article__container">
<h1 class="article__title title">Заголовок страницы</h1>
<div class="article__content content">
<h1>Заголовок h1</h1>
<h2>Заголовок h2</h2>
<h3>Заголовок h3</h3>
<h4>Заголовок h4</h4>
<h5>Заголовок h5</h5>
<h6>Заголовок h6</h6>
<p>
Абзац текста, содержащий <b>жирный</b> текст и <a href="https://tagree.ru/" target="_blank">ссылку</a>.
</p>
<ul>
<li>Элемент списка 1</li>
<li>Элемент списка 2</li>
<li>Элемент списка 3</li>
</ul>
<ol>
<li>Элемент списка 1</li>
<li>Элемент списка 2</li>
<li>Элемент списка 3</li>
</ol>
<blockquote>
Здесь содержится цитата
</blockquote>
<img src="assets/images/image.jpg" alt="Подпись картинки">
</div>
</div>
</article>
</main>
@@include('blocks/page-footer.html')
</body>
</html>
Здесь необходимо отойти от БЭМ-методологии. Стилизация элементов должна осуществляться исключительно по тегам, так как тестовый редактор ничего не знает о наших классах и принципах построения разметки.
Универсального набора правил не существует, многое зависит от возможностей текстового редактора и требуемого дизайна, но для нашего проекта хорошо подойдёт следующее:
.content {
color: @black;
font-family: @font1;
font-size: 16px;
font-weight: 400;
font-style: normal;
line-height: 1.375;
word-wrap: break-word;
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 1.3em 0 0.8em;
font-family: @font1;
color: @black;
font-weight: 600;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
h1 {
font-size: 32px;
}
h2 {
font-size: 28px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 20px;
}
h5 {
font-size: 18px;
}
h6 {
font-size: 16px;
}
ol,
ul,
p {
margin: 20px 0;
font-family: @font1;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
ul,
ol {
position: relative;
padding: 0;
list-style: none;
font-family: @font1;
}
ul > li {
box-sizing: border-box;
position: relative;
padding-left: 20px;
&::before {
content: "";
display: block;
position: absolute;
top: 8px;
left: 0;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: @red;
pointer-events: none;
}
}
ol {
counter-reset: li;
padding: 0;
}
ol > li {
counter-increment: li;
&::before {
content: counter(li) + ". ";
box-sizing: border-box;
display: inline-block;
min-width: 20px;
color: @red;
white-space: pre;
}
}
ul > li,
ol > li {
margin: 0 0 8px;
cursor: default;
&:last-child {
margin-bottom: 0;
}
}
img,
iframe,
figure {
display: block;
max-width: 700px;
}
& > img,
& > iframe,
& > figure {
margin: 30px 0;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
iframe {
border: none;
outline: none;
}
figure {
img {
max-width: 100%;
margin: 0;
}
}
figcaption {
margin: 15px 0;
color: fade(@black, 60%);
font-weight: 500;
font-size: 13px;
text-align: left;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
img {
&[align],
&.alignright {
margin: 5px 0;
& + figcaption {
display: none;
}
}
&[align="right"],
&.alignright {
margin-left: 10px;
}
&.alignright {
float: right;
}
&[align="left"],
&.alignleft {
margin-right: 10px;
}
&.alignleft {
float: left;
}
}
a {
font-weight: 600;
color: @black;
text-decoration: underline;
transition: color 0.2s;
cursor: pointer;
&:hover {
color: @red;
}
}
blockquote {
position: relative;
margin: 30px 0;
padding: 0 0 0 20px;
color: fade(@black, 90%);
font-style: normal;
font-weight: 600;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
&::before {
content: "";
display: block;
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background-color: @red;
}
}
b {
font-weight: 700;
}
}
Результат:
Теперь можно задать текстовую разметку на детальной странице мероприятия.
7. Материалы для самостоятельного изучения
- Формы:
https://developer.mozilla.org/ru/docs/Web/HTML/Element/form - Таблицы:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table
8. Первое испытание
Итак, мы примерно на середине пути. На данный момент мы изучили основы HTML и CSS, разобрали блочную модель и позиционирование, познакомились с формами и многими другими важными компонентами web-страниц, освоили средства автоматизации рабочего процесса.
Сейчас вам предлагается промежуточное испытание: предоставить на проверку git-репозиторий с учебным проектом в соответствии с предложенными ниже критериями.
Вы можете предоставить ссылку на конкретную ветку репозитория, продолжив учебу и работу в иной ветке вашего проекта.
Время на выполнение учебной работы не ограничено.
Критерии
- Структура проекта и средства автоматизации соответствуют представленным на 5 уроке «Оптимизация и автоматизация«;
- Выполнена HTML-разметка всех страниц и всех элементов на страницах в соответствии с самым крупным desktop-макетом учебного проекта в Figma. Карта на главной странице в разделе «Контакты» на данном этапе должна представлять собой обычное изображение;
- Собранные HTML-документы проходят проверку на валидность https://validator.w3.org/nu/#textarea и не содержат явных ошибок. Допускаются только предупреждения (
warning
, жёлтого цвета); - HTML-разметка соответствует гайдлайну, предоставленному на 1 уроке «Введение. Знакомство с HTML«;
- CCS-код соответствует гайдлайну, предоставленному на 2 уроке «Основы CSS и методологии«;
- К страницам подключен один минифицированный стилевой файл внутри
<head>
; - HTML-разметка и CSS-код выполнены в соответствии с методологией БЭМ;
- Подобраны подходящие с точки зрения семантики HTML-теги для каждого элемента;
- Подключены правильные шрифты, их размеры, цвета и толщина соответствуют таковым в макетах;
- Отсутствует транслит в названиях классов, атрибутов и т.п.;
- Все расстояния между HTML-элементами соответствуют макету или округлены до
5px
в ближайшую сторону. Таким образом неточность вёрстки составляет+/-2
пикселя по высоте и ширине для всех размеров и расстояний. - Вёрстка проходит тест на переполнение контентом: наполнение заголовков и текстовых блоков большим количеством текста, изображения неподходящего размера, а также изменение количества блоков в потоке не должны приводить к поломке вёрстки;
- Стили каждого БЭМ-блока вынесены в отдельный соответствующий файл CSS-препроцессора.
- Вложенность селекторов допускается только в крайних случаях: вложенные элементы, затронутые БЭМ-модификатором родительского блока, активные состояния элементов (например, при наведении мыши), состояния элементов форм в активном состоянии (например,
:checked
), и т.п.; - Все ссылки и кнопки реагируют на наведение мыши, подсвечивая элемент указанным в макете способом (исключения — логотип в шапке и svg-иконки, заданные с помощью символьного svg-спрайта).
- На страницах отсутствует горизонтальная прокрутка. Элементы выступающие за пределы экрана должны быть обрезаны с помощью CSS;
- Код должен быть максимально кроссбраузерным, протестируйте свою работу во всех популярных браузерах: Google Chrome, Mozilla Firefox, Microsoft Edge, Safari. Поддержка IE11 не требуется, проверка кода в Safari от Apple может быть пропущена, если у вас нет такой возможности;
- В проекте должен присутствовать файл
.gitignore
с включёнными каталогамиnode_modules
иdist
. В репозитории не следует хранить npm-пакеты и собранную сборку проекта, только исходники.