Вступление

Меня зовут Николай и я Frontend-разработчик. Хочу рассказать о самых распространённых ошибках в вёрстке современных проектов.

Дело в том, что лишь малая часть современных фронтендеров обращает внимание на работу с HTML и CSS, предпочитая готовые решения, вроде UI-библиотек и систем сеток. Но эти решения неидеальные и приходится дописывать обёртки вокруг них, видоизменять код, переписывать стили и совершать прочие действия для соответствия требованиям проекта. Тут-то и начинаются проблемы: вёрстка местами становится избыточной, стили переназначются через important и с каждым релизом проект всё сложней поддерживать. Я уже не говорю об удобстве использования и доступности. Об этом думают вообще в последнюю очередь.

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

Содержание

Используйте правильные теги.

Как правильно вкладывать теги друг в друга.

Работа с медиаконтентом.

Пишем таблицы на HTML правильно.

a или button? Работа с интерактивными элементами и как выбрать правильный тег.

Различный теги для медиа-контента.

Прекратите писать велосипеды! Как мы можем стилизовать дефолтные HTML-элементы.

Пишем доступные формы.

Избыточная вёрстка. Как облегчить разметку.

Современные фишки HTML и CSS способные облегчить нам жизнь.

Экспериментальные технологии, входящие в стандарт.

Используйте правильные теги

Исторически так сложилось, что HTML служит для описания документов. То есть язык гипертекстовой разметки был придуман для обмена документами (в основном научного характера) и не предназначался для построения сложных веб-приложений и сайтов. Благодаря развитию стандарта стало полегче, но большинство современных разработчиков всё ещё предпочитают <div> в качестве главного тега и засовывают в него любой контент, вплоть до изображений (через background-image). И я прекрасно их понимаю, <div> — очень удобный тег: у него нет встроенных стилей, его можно вкалывать в другие дивы. Чем не кандидат на лучший тег. Но при таком использовании тегов мы теряем главные преимущества HTML:

  • семантику — чёткую структуру контента, где каждый тег говорит о том, зачем он здесь и что ожидается внутри;

  • доступность — HTML может рендериться не только браузером, но и другими инструментами, вроде скрин-ридеров, роботов-поисковиков и т.д. И в наших силах упростить для них парсинг страниц.

Про какие теги нам следует стоит помнить?

Структурные теги документа

Почти любой сайт или приложение можно разбить на 3 большие части: <header>, <main> и <footer>. Сейчас это стало неким стандартом в дизайне. Некоторые части приложения повторяются от страницы к странице, и мы можем выделить их в отдельные части (шапку и подвал).

Шапка — это контент вверху страницы. Там обычно размещается логотип, навигационное меню и другие элементы, которые должны быть доступны пользователю с любой страницы. Тег <header> не обязательно один на странице, он может озаглавливать любую независимую часть (например, быть частью модального окна).

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

Тег <main> обычно обозначает место для основного контента, который не повторяется от страницы к странице.

Плохо

<body>
	<div class="header">
		...
	</div>
	<div class="main">
		...
	</div>
	<div class="footer">
		...
	</div>
</body>

Хорошо

<body>
	<header>
		...
	</header>
	<main>
		...
	</main>
	<footer>
		...
	</footer>
</body>

Помимо трёх базовых семантических тегов существует ряд других. Разберём их ниже.

<article>

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

<section>

Неотделяемая от основного контента секция на странице. Например, это может быть блок на лендинге. Чаще всего имеет заголовок.

<aside>

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

<nav>

Блок навигации с ссылками на другие страницы или разделы текущей страницы. Может использоваться только для основной навигации, а не для каждой группы ссылок. Например навигацию в <footer> не имеет смысла упаковывать в <nav>, так как подвал сам по себе предполагает присутствие навигационных элементов. И этот тег не обязательно должен включать в себя список ссылок. Туда может входить навигация любого типа, главное, чтобы она считалась основной.

<address>

В этот тег нужно вкладывать контактные данные. У него по-особенному работает «область видимости» — контактные данные в <address> относятся к ближайшему родительскому блоку <article>, либо к <body>, если он находится вне <article>.

Заголовки

Как и в любом документе на HTML-странице могут содержаться заголовки. По стандарту мы обязаны всегда указывать заголовок первого уровня <h1>. Остальные уровни опциональны, но они должны быть в иерархической последовательности! Это значит, что мы не можем <h3> поставить после <h1>. Чтобы лучше это понять, посмотрим код ниже:

<body>
	<header>
		...
	</header>
	<main>
		<h1> Наша кондитерская самая кондитерская из всех кондитерских </h1>
		...
		<section>
			<h2> Почему наши булочки лучшие? </h2>
			...
				<h3> Мука высочайшего сорта </h3>
				...
				<h3> Много корицы </h3>
				...
					<h4> Корица со Шри-Ланки</h4>
					...
				<h3> Минимум сахара </h3>
				...
			<h4>
		</section>
	</main>
	<footer>
		...
	</footer>
</body>

Как вы видите, заголовки выстраиваются в иерархию и идут один за одним, формируя логичную структуру.

По поводу использования нескольких заголовков <h1>: вы МОЖЕТЕ использовать несколько заголовков первого уровня, если это требуется на странице. Когда-то давно некоторые злые SEO-специалисты настоятельно не рекомендовали так делать, хотя спецификация ничего не говорит на этот счёт. Сейчас мы, конечно, не узнаем действительно ли поисковики снижали сайт в выдаче за использование двух и более заголовков первого уровня, но уже даже многие SEOшники признали, что этот фактор малозначителен при ранжировании сайтов.

Блочные теги

<p>

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

<figure> и <figcaption>

Это иллюстрация с необязательной подписью. Во многих книгах изображения подписываются как «Рис. 1 — такой-то объект». Вот это и есть <figure>. Но в рамках HTML назначение этого тега гораздо шире. Мы можем разместить внутри цитату (см. ниже), фрагмент кода, какую-нибудь диаграмму. В общем <figure> — это любой объект с подписью. Подпись размещается внутри тега <figcaption>, который, в свою очередь, вкладывается в <figure>.

<figure>
	<img src="https://example.com/cat.jpg" alt="Сердитый кот">
	<figcaption>Кот, который зол на своего хозяина</figcaption>
</figure>

<blockquote>

Тег для вставки длинных цитат. Может иметь аттрибут cite, в котором указывается URL на источник цитаты, а также хорошо совместим с тегом <figure>, где в <figcaption> можно указать автора и название источника.

<figure>
	<blockquoute cite="https://www.youtube.com/watch?v=ZXsQAXx_ao0">
		Just Do It!
	</blockquote>
	<figcaption>
		Shia LaBeouf, <cite>Motivational Speech</cite>
	</figcaption>
</figure>

<hr>

Одиночный тег для разделения контента. Про него забывают и заменяют на border-bottom, но помимо визуального отображения этот тег несёт семантический смысл — тематическое разделение абзацев.

<pre>

Тег для вывода предварительно отформатированного текста. Имеет ограниченную область использования — ASCII-арт, вывод программного кода. Не рекомендую использовать для других задач, так как тег довольно ненадёжен и непредсказуем. Например, мы потеряем всё форматирование, если сборщик проекта минифицирует HTML.

Списки

Списки в вебе просто везде! Но очень редко их верстают как списки. Например, преимущества компании на лендинге это что? Правильно, список. Они бывают двух видов: упорядоченные и неупорядоченные. Я в этот раздел также добавил список описаний Description list.

<ul>

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

  • cписок ингредиентов для рецепта;

  • преимущества компании;

  • партнёры компании.

<ul>
	<li>Удобная оплата</li>
	<li>Быстрая доставка</li>
	<li>Гарантия в 1 год</li>
</ul>

<ol>

Упорядоченный список применяется тогда, когда нам важен порядок элементов. Например:

  • пошаговая инструкция;

  • этапы работы.

<ol>
	<li>Оформляете заявку</li>
	<li>С вами связывается менеджер для уточнения деталей</li>
	<li>Совершаете оплату</li>
	<li>Ожидаете доставку</li>
</ol>

<dl>, <dd>, <dt>

Списки описаний применяются для формирования списков терминов.

<dl>
	<dt>HTML</dt>
	<dd>Язык разметки гипертекста, с помощью которого формируют контент веб-страницы</dd>

	<dt>CSS</dt>
	<dd>Язык для описания стилей веб-страницы</dd>

	<dt>JS</dt>
	<dd>Язык программирования, часто применяемый для написания веб-приложений</dd>
</dl>

Строчные теги

<b>, <i>, <u>, <s>

Чудесные теги, которые чаще всего используют не по назначению. Они несут исключительно визуальное выделение текста. Если вы сбросите их стили, то они ничем не будут отличаться от обычного текста. В данный момент их можно использовать как теги для дополнительного выделения текста, которое вы оформите с помощью CSS. И да, тег <i> НЕ предназначен для иконок.

<em>

Как и <i> выделяет текст курсивом. Но зачем нам два тега для одного и того же? В том то и дело, что они разные. <i>, как говорилось выше, не несёт никакого семантического смысла, это просто визуальное выделение, а <em> делает акцент на обёрнутом им тексте, который меняет смысл всего предложения. Например:

Я <em>просто обожаю </em>, когда верстальщики используют только дивы.

<strong>

Браузер выделяет текст обёрнутый тегом <strong> полужирным. Но помимо визуального выделения, текст обретает семантический смысл — большую важность по сравнению с остальным текстом вокруг.

<cite> и <q>

Оба тега связаны с цитирований, но применяются в разных случаях. <cite> — тег, в который мы оборачиваем текст, который отсылается к другому документу/произведению/etc.

Больше информации вы сможете найти в стандарте <cite>[ISO-0000]</cite>

<q> похож на <blockquote>, разница лишь в том, что <q> применяется для строчных цитат.

<q cite="https://russian.rt.com/business/news/966657-rubl-dollar-evro">
	Рубль растёт к доллару и евро
</q> — сообщает RT со ссылкой на ФАН.

<code>

Применяется для оформления программного кода внутри текста. Если требуется вывести многострочный блок кода, то лучше использовать <code> в связке с тегом <pre>.

<time>

Тег для обозначения даты и времени. У него может быть атрибут datetime, куда необходимо передать дату и время в формате ISO.

<time datetime="1995-11-24">24 ноября 1995 года</time>

<sub> и <sup>

Используются для добавления в текст индексов и степеней. Удобны для описания формул.

x<sub>1</sub> + x<sub>2</sub> = y<sup>2</sup>
<!-- Икс первый плюс икс второй равно игрек в квадрате -->

<del> и <ins>

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

Вася пришёл домой в
<del><time>19:00</time></del>
<ins><time>23:00</time></ins>

<br>

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

Интерактивные элементы

<details>

Нативный дропдаун прямо в HTML! На самом деле не совсем так. <details> применяется, чтобы скрыть часть информации, которую можно получить, кликнув по кнопке, описанной во внутреннем теге <summary>.

Рубль растет на фоне заявлений Запада о введении санкций против России
<details>
    <summary>Подробнее</summary>
    Согласно данным валютных торгов на Московской бирже, по состоянию
    на 22.40 мск курс доллара находился на уровне 78,7 рубля (-1,6%),
    курс евро снижался до 89,3 рубля (-0,9%).
</details>

Внимание! Данный тег не поддерживается IE и старыми версиями основных браузеров.

Другие интересные теги

<abbr>

Тег для аббревиатур.

<abbr title="HyperText Markup Language">HTML</abbr> — основной язык разметки веб-приложений

<dfn>

Тег для выделения термина. Элемент<p>, пара <dt>/<dd> или <section>, который является ближайшим предком <dfn> считается определением термина.

<p>
	<dfn>JavaScript</dfn> — язык программирования,
	используемый в основных веб-браузерах.
</p>

<kbd>

Используется для выделения названия клавиш в клавиатурных сочетаниях.

Чтобы открыть диспечер задач, нажмите сочетание клавиш
<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Esc</kbd>.

<samp>

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

<p>
Приложение упало с ошибкой:<br>
<samp>404 Неизвестный ресурс</samp>

<var>

Элемент для вывода математических переменных

Для рассчёта расстояния <var>S</var>, необходимо
перемножить скорость <var>V</var> на время <var>t</var>.

<bdi> и <bdo>

Теги, связанные с направлением текста ltr и rtl. Необходимы, когда мы встраиваем в текст, написанный языком в одном направлении, фразу или предложение написанное в другом.

<bdi> изолирует от окружающего текста фрагмент, который может поменять направление (но не обязательно поменяет).

<bdo> в свою очередь, переопределяет направление текста так, что текст внутри тега отображается в другом направлении, нежели чем окружающий.

<p dir="ltr">
	Это <bdi>арабское слово</bdi> будет перевёрнуто.
</p>
<!--
	Это оволс еоксбара будет перевёрнуто.
-->

<mark>

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

<meter>

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

Имеет следующие аттрибуты:

  • min — минимальное значение шкалы;

  • max — максимальное значение шкалы;

  • low — предел, при достижении которого, значение считается низким;

  • optimum — предел, при достижении которого, значение считается оптимальным;

  • high — предел, при достижении которого, значение считается высоким;

  • value — собственно само значение.

<p>Температура воды</p>
<meter value="0" max="100" low="10" high="60">Низкая</meter>
<meter value="30" max="100" low="10" high="60">Нормальная</meter>
<meter value="80" max="100" low="10" high="60">Горячая</meter>
<meter value="100" max="100">Кипяток</meter>

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

<progress>

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

<progress max="100" value="70">70%</progress>

<wbr>

Одиночный тег, указывающий, в каком месте можно переносить цельную строку. Является аналогом символа ­­&shy;, с той лишь разницей, что не добавляет символ переноса в конце строки.

<ruby>, <rt>, <rp>

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

<big>, <small>, <tt> и прочая эзотерика

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

Заключение части 1

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

Также, я ничего не сказал по <div> и <span>, которые являются базовыми элементами для вёрстки. Их стоит использовать только в том случае, когда ничто из вышеперечисленного не подошло.

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


  1. lesskop
    10.03.2022 16:04
    +9

    Как правильно верстать кликабельное содержание статьи на Хабре в 2022 году?


    1. Clickrouc Автор
      11.03.2022 09:12

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


  1. webstr-samarcev
    10.03.2022 16:11

    Неплохо, ждать 2-й части?


    1. Clickrouc Автор
      11.03.2022 09:14

      Да, в этом месяце выложу :)


  1. AlexElkin
    10.03.2022 19:20

    Автор не знает как работают скриниридеры...


    1. gBACTAKAHA
      10.03.2022 21:00
      +2

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


      1. Clickrouc Автор
        11.03.2022 09:13

        Про a и button будет отдельная статья. Я намерено не расказывал о них в этой части.


  1. jesaiah4
    10.03.2022 19:46

    Подскажите нормальную статьи или видео на русском , про то как считаются все эти max-height , min-height от родителей если у тех например только max-height ,а ты для детей ставишь процентные соотношение и т.д.


    1. gBACTAKAHA
      10.03.2022 21:05

      Что может быть проще?

      Все что max-*/min-* это про максимальное/минимальное значение. На родителей и их значения пофиг. Главное чтобы значение не было указано больше/меньше (если min). То что у вас пересчитается, если было задано в процентах или иных не постоянных величинах, в пиксели в итоге вы можете увидеть в девтулс во вкладке computed. Просто сами попробуйте и все увидите.


      1. jesaiah4
        10.03.2022 21:31

        ну это же не так

        вот документация http://www.w3.org/TR/CSS21/visudet.html#min-max-heights

        в ней говорится "max-height on a child, it is a percentage of the parent's actual height"

        Вот вам пример когда ребенок превышает max-height родителя , даже имея min-height:0; (в режиме flex)

        sandbox: (красный прямоугольник это как раз ребенок который неверно считается)

        https://play.tailwindcss.com/bvfy0kF5Nz

        Не всё так просто как вы думаете.


    1. Clickrouc Автор
      11.03.2022 12:18

      Надо написать что-то подобное, спасибо за идею.


  1. Luciusegorov
    11.03.2022 08:50
    +5

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


    1. Clickrouc Автор
      11.03.2022 09:14
      +1

      Отредактирую позже, сделаю визуализацию. Спасибо за обратную связь!


      1. Luciusegorov
        11.03.2022 14:16

        Большое спасибо Вам за статью!


    1. AlexElkin
      11.03.2022 09:59

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


      1. domix32
        11.03.2022 12:12
        +1

        В таком случае собранные в песочницах примеры прилинковать - тоже неплохой план.


      1. Luciusegorov
        11.03.2022 14:15
        +1

        1) В таком случае можно все верстать дивами+css, думаю

        2) Читал утром с мобильного телефона


        1. AlexElkin
          11.03.2022 15:34

          Ну если вы используете тэги только для внешнего вида, то возможно так даже лучше.

          Уж лучше дивы сем адова структура заголовков потому что в макете буковки жирные и разного размера.


    1. jesaiah4
      11.03.2022 10:12

      а мне лично не хватает аналога p тега , чтобы он не имел отступы маргены , так же только для текста и имел 100% ширины.


      1. SkyHobbit
        11.03.2022 11:13

        Тэг <p> и так имеет 100% ширины и отступы сверху и снизу. Или вам нужны отступы по бокам, но зачем? Может быть подойдут <blockquote> или <pre> ?


        1. jesaiah4
          11.03.2022 11:26

          как раз P для обзацев т.к. имеет отстоп.

          а нужен клон P , но без отступов


          1. Clickrouc Автор
            11.03.2022 12:05
            +1

            Ну так заведите класс. Будет что-то вроде

            <p class="without-margins">

            А в стилях укажите

            .without-margins {
              margin: 0;
            }

            Бессмысленно плодить теги для одного и тоже с разными стилями, для этого и был придуман CSS.


          1. SkyHobbit
            11.03.2022 13:02

            Тогда почему <span> не подходит?


            1. Clickrouc Автор
              11.03.2022 20:11

              <span>, во-первых строчный по-умолчанию, а во-вторых семантически ничего не значит, в отличии от абзаца.


  1. doox911
    11.03.2022 08:54

    Годненько. Но это только азы.


    1. Clickrouc Автор
      11.03.2022 09:14

      В следующих частях погрузимся глубже.


  1. jesaiah4
    11.03.2022 10:13
    +1

    По статьи мне кажется вы очень плохо раскрыли section article где когда испльзовать, ком в ком может быть


    1. Clickrouc Автор
      11.03.2022 12:06

      Спасибо за адекватную критику! Есть уже пара задач по доработке материала (либо раскрытие этих тем в следующих).


    1. superoleg111
      12.03.2022 19:34

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

      А так в целом статья понравилась, я относительно новичок в этом деле, поэтому помогла устаканить некоторые вещи в голове


  1. wadowad
    11.03.2022 13:07

    На картинке к статье, в которой рассказывается, как правильно верстать в 2022 году, изображён закрытый одиночный тег meta.


    1. Clickrouc Автор
      11.03.2022 20:12

      Сори, картинка из гугла, я не дизайнер, ничего нормально не придумал подставить.


  1. Dron007
    12.03.2022 23:39

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