Урок 5. Семантическая разметка (header, nav, main, section, article, footer). Расширенные селекторы, наследование. Базовое выравнивание
Когда мы писали первые страницы, мы использовали только <div> для построения структуры. У такого подхода есть минус: страница становится «безликой» для поисковых систем и вспомогательных технологий — например, экранных читалок для людей с нарушениями зрения.
Семантика — это когда каждый тег имеет смысл и отражает предназначение содержимого: <header> — шапка сайта, <nav> — раздел навигации, <main> — основное содержимое, <section> — отдельный смысловой блок внутри main, <article> — самостоятельный кусок контента (новость, пост, товар), <footer> — нижняя часть страницы.
Зачем это нужно: поисковики лучше понимают, где на странице важный контент (SEO); экранные читалки могут быстро перемещаться между header, nav, main, footer (доступность); программисту проще читать структуру страницы (поддержка кода). Семантика — это не про «красивые» теги ради красоты, а про удобство для пользователей и разработчиков.
<!-- Было -->
<div class="header">
<h1>Название сайта</h1>
<div class="nav">
<a href="#">Главная</a>
<a href="#">О нас</a>
</div>
</div>
<div class="main">
<div class="section">
<div class="article">
<h2>Первая статья</h2>
<p>Текст первой статьи...</p>
</div>
<div class="article">
<h2>Вторая статья</h2>
<p>Текст второй статьи...</p>
</div>
</div>
</div>
<div class="footer">
<p>Все права защищены © 2025</p>
</div><!-- Стало -->
<header>
<h1>Название сайта</h1>
<nav>
<a href="#">Главная</a>
<a href="#">О нас</a>
</nav>
</header>
<main>
<section>
<article>
<h2>Первая статья</h2>
<p>Текст первой статьи...</p>
</article>
<article>
<h2>Вторая статья</h2>
<p>Текст второй статьи...</p>
</article>
</section>
</main>
<footer>
<p>Все права защищены © 2025</p>
</footer>Оба варианта выглядят одинаково в браузере — но второй лучше понимается поисковиками и вспомогательными технологиями.
Расширенные селекторы позволяют выбирать элементы не только по имени тега, классу или id, но и в зависимости от их положения в структуре документа — вложенности, соседства — а также объединять несколько селекторов в одно правило.
Выбирает все элементы B, которые находятся внутри A на любом уровне глубины, не обязательно как прямые дети.
main div {
background: #fff8e1;
}Захватит все div где-нибудь внутри main — будь то прямые дети, внуки или ещё глубже. Будьте аккуратны: descendant-селектор может затронуть больше элементов, чем ожидается, если структура гибкая.
Выбирает только те B, которые являются прямыми детьми A.
main > article {
margin-bottom: 24px;
}Сработает только для article, расположенных непосредственно внутри main. Если article вложен глубже (например, внутри section), правило не сработает — используйте этот вид селектора, когда важно не затрагивать более глубокие уровни вложенности.
Выбирает элемент B, который непосредственно следует за A на том же уровне вложенности.
h2 + p {
margin-top: 8px;
color: #333;
}Применится только к p, который идёт сразу после h2 в том же родителе. Удобно для типичного паттерна «заголовок + первый абзац» — например, чтобы настроить именно ему отступ.
Выбирает все элементы B, которые идут после A и имеют того же родителя — не обязательно сразу следующие.
h2 ~ p {
color: #666;
}Применится ко всем p после h2 в рамках одного родителя, а не только к первому.
Позволяет задать один и тот же набор свойств сразу нескольким селекторам одним правилом.
h1,
h2,
h3 {
font-family: "Arial", sans-serif;
color: #222;
}Выбирает элементы по наличию или значению указанного атрибута.
a[target="_blank"] {
color: #c00;
text-decoration: underline;
}Применится ко всем ссылкам, которые открываются в новой вкладке. Есть и другие формы: [attr] (просто наличие атрибута), [attr^="start"] (значение начинается с...), [attr$="end"] (заканчивается на...), [attr*="contains"] (содержит подстроку).
| Селектор | Что выбирает |
|---|---|
A B |
Любой потомок B внутри A, на любой глубине |
A > B |
Только прямой ребёнок B у A |
A + B |
B, идущий сразу после A (смежный сосед) |
A ~ B |
Все B после A на одном уровне |
A, B |
Группировка — общее правило для нескольких селекторов |
A[attr="value"] |
Элементы A с заданным атрибутом/значением |
Некоторые CSS-свойства по умолчанию наследуются от родителя к потомку: если задать их у родительского элемента, дочерние автоматически возьмут это значение, если у них не указано своё собственное. Это уменьшает повторяемость кода.
color, font-family, font-size (частично), font-style/font-weight, line-height, text-align (в некоторых случаях), visibility.
body {
color: #222;
font-family: Arial, sans-serif;
}
main p {
/* не задаём color — он наследуется от body и будет #222 */
}Задав color и font-family в body, вы обеспечиваете единый текстовый стиль по всей странице, не прописывая его у каждого элемента отдельно.
margin, padding, border, background, width, height, display, position, float, clear. Причина: эти свойства определяют физическую «коробку» элемента (box-model), и логично, что у каждого дочернего элемента она своя, а не унаследованная от родителя.
<main>
<article>
<h2>Заголовок</h2>
<p>Первый абзац — унаследует цвет от body.</p>
<p class="special">В этом абзаце цвет переопределён.</p>
</article>
</main>body {
color: #333;
}
.special {
color: #a00; /* переопределяет унаследованный цвет */
}Оба параграфа по умолчанию получат color: #333 от body, но у .special явно задан другой цвет — он переопределит унаследованное значение.
inherit принудительно наследует значение от родителя, даже если свойство обычно не наследуется (p { color: inherit; }). initial сбрасывает свойство к браузерному значению по умолчанию. unset ведёт себя как inherit, если свойство наследуемое, или как initial, если нет. На базовом уровне используются редко, но полезны для точечного сброса стилей.
<div class="parent">
Родительский текст
<p>Просто текст</p>
<p class="red">Красный текст</p>
<p class="default">Обычный текст</p>
<p class="text">Еще один текст</p>
</div>.parent {
color: blue;
}
p {
color: inherit;
}
.red {
color: red;
}
.default {
color: initial;
}
.text {
color: unset;
}Когда одно и то же свойство задано несколькими правилами одновременно, браузер выбирает, какое из них применить, руководствуясь каскадом и специфичностью.
Порядок применения (упрощённо): правила с !important имеют наивысший приоритет (использовать без крайней необходимости не стоит); при отсутствии !important побеждает более специфичный селектор; если специфичность одинаковая — побеждает правило, идущее ниже в CSS-файле.
<p class="text">Пример</p>.text {
color: blue !important;
}
.text {
color: red;
}Упрощённая шкала: inline-стиль (style="...") — самый высокий вес; id (#id) — большой вес; класс, атрибут, псевдокласс (.class, [attr], :hover) — средний вес; тег или псевдоэлемент (h1, ::before) — низкий вес.
p { color: red; } /* специфичность: 1 */
.intro p { color: blue; } /* специфичность: 10 + 1 = 11 */
#main .intro p { color: green; } /* специфичность: 100 + 10 + 1 = 111 */Если элемент <p> находится внутри #main и .intro одновременно, победит color: green — потому что #main .intro p наиболее специфичен из трёх.
Селекторы тегов — для глобальных, базовых правил. Классы — основной инструмент для повторного использования стилей. id — только для действительно уникальных случаев, с осторожностью (повышает специфичность и усложняет последующее переопределение). !important — избегать без крайней необходимости.
<header>
<h1>Мой сайт</h1>
<nav>
<a href="#">Главная</a>
<a href="#">Блог</a>
<a href="#">Контакты</a>
</nav>
</header>
<main>
<section>
<article>
<h2>Первая статья</h2>
<p>Немного текста...</p>
</article>
<article>
<h2>Вторая статья</h2>
<p>Ещё немного текста...</p>
</article>
</section>
</main>
<footer>
<p>Контакты: info@example.com</p>
</footer>body {
font-family: Arial, sans-serif;
color: #222; /* наследуется всеми текстовыми элементами внутри */
line-height: 1.5;
}
header {
background-color: #2b6cb0;
color: white;
padding: 20px 0;
text-align: center;
}
/* descendant-селектор: все ссылки внутри header nav */
header nav a {
display: inline-block;
margin: 0 12px;
color: white;
text-decoration: none;
}
/* дочерний селектор: только section прямо внутри main */
main > section {
background: #f8f8f8;
padding: 20px;
}
/* дочерний селектор: только article прямо внутри main > section */
main > section > article {
display: inline-block;
width: 48%;
vertical-align: top;
background: white;
border: 1px solid #ddd;
padding: 15px;
margin: 1%;
box-sizing: border-box;
}
/* соседний селектор: первый параграф после заголовка статьи */
main article h2 + p {
margin-top: 8px;
color: #444;
}
/* селектор атрибута: внешние ссылки */
a[target="_blank"] {
color: #c00;
}
footer {
background: #f2f2f2;
text-align: center;
padding: 15px;
color: #333;
}body задаёт базовый color и font-family, унаследованные всеми текстовыми элементами. header nav a — descendant-селектор, находит все ссылки именно внутри навигации шапки. main > section и main > section > article — дочерние селекторы, чётко ограничивающие область влияния только прямыми потомками, что защищает от случайного попадания вложенных элементов на более глубоких уровнях. h2 + p настраивает отступ именно первому абзацу сразу после заголовка.
До появления Flexbox и Grid (разберём их в отдельных модулях) выравнивание строилось на display, text-align, margin и float. Эти техники по-прежнему полезны — они встречаются в старых проектах, и понимание истории вёрстки помогает лучше ценить современные инструменты.
<div class="wrapper">
<div class="box">
Это обычный блочный элемент
</div>
<nav class="menu">
<a href="#">Главная</a>
<a href="#">Каталог</a>
<a href="#">Контакты</a>
</nav>
<div class="columns">
<div class="column">Колонка 1</div>
<div class="column">Колонка 2</div>
<div class="column">Колонка 3</div>
</div>
<footer class="footer">
Подвал сайта
</footer>
</div>.wrapper {
width: 900px;
margin: 30px auto;
border: 1px solid #ccc;
padding: 20px;
}.menu {
text-align: center;
}
.menu a {
display: inline-block;
padding: 10px;
background: lightblue;
}Все <a> встали в строку и выровнялись по центру, потому что родительский div применил text-align: center — это свойство наследуется и влияет на строчные элементы внутри.
Если элемент блочный, он по умолчанию занимает всю ширину строки. Чтобы центрировать сам блок, нужно задать ему фиксированную ширину и margin: 0 auto:
.box {
width: 300px;
background-color: lightgreen;
margin: 0 auto;
padding: 20px;
}margin: 0 auto означает: сверху/снизу отступ 0, а слева/справа — автоматически поровну распределённое оставшееся пространство, что и центрирует блок.
.menu {
text-align: center;
}
.menu a {
display: inline-block;
padding: 10px 20px;
margin: 5px;
background-color: lightcoral;
color: white;
text-decoration: none;
}Классический паттерн: inline-block превращает ссылки в блочные «кнопки», а text-align: center у родителя выравнивает их как строку.
.columns {
text-align: center;
}
.column {
display: inline-block;
width: 30%;
margin: 1%;
background: lightyellow;
text-align: center;
}Колонки встают в ряд и автоматически переносятся на новую строку, если ширины экрана не хватает.
.column {
float: left;
width: 30%;
margin: 1%;
background-color: lightpink;
text-align: center;
}
.footer {
clear: both;
background-color: lightgray;
padding: 20px;
text-align: center;
}Колонки прижимаются в ряд слева; clear: both у подвала гарантирует, что он не «поднимется» рядом с плавающими колонками (та же логика, что мы разбирали в Уроке 4).
| Подход | Особенность |
|---|---|
text-align + inline-block |
Удобен для центрирования и меню, но между inline-block-элементами есть небольшая «щель» — след от пробела в HTML-коде |
margin: 0 auto |
Подходит только для центрирования блочного элемента с фиксированной шириной |
inline-block для колонок |
Просто и без побочных эффектов на поток документа, но требует внимания к пробелам между элементами |
float |
Универсален для сложных сеток, но нарушает нормальный поток документа — после плавающих элементов нужно явно «очищать» обтекание через clear |
- Что такое семантическая разметка и чем она отличается от разметки через
divбез классов, объясняющих назначение? - Чем
<section>отличается от<article>? - В чём разница между селектором потомков (
A B) и дочерним селектором (A > B)? - Чем соседний селектор (
A + B) отличается от общего соседа (A ~ B)? - Какие CSS-свойства обычно наследуются от родителя к потомку, а какие — нет? Приведи по два примера каждого вида.
- Как рассчитывается специфичность селектора (упрощённо), и какой из трёх селекторов победит:
p,.intro p,#main .intro p— если все они конфликтуют для одного и того же элемента? - Что произойдёт, если два CSS-правила имеют одинаковую специфичность и конфликтуют между собой?
- Зачем нужен селектор атрибутов, например
a[target="_blank"]? Приведи практический сценарий использования. - Почему у
margin: 0 autoэлемент обязательно должен иметь заданную фиксированную ширину, чтобы центрирование сработало? - Почему при использовании
floatдля колонок часто требуетсяclear: bothу следующего за ними элемента?
Возьми простую структуру страницы, написанную только через <div> (шапка, основной контент, подвал), и перепиши её на семантические теги: <header>, <main>, <footer>. В <header> добавь <h1> с названием сайта и <nav> с тремя ссылками. В <main> создай два <article>, каждый с заголовком <h2> и текстом. В <footer> укажи email и телефон.
На основе разметки из Задания 1 напиши CSS, используя каждый из изученных видов селекторов:
- Дочерний селектор — рамка для всех
article, лежащих прямо внутриmain. - Соседний селектор — увеличенный
margin-topдля абзаца, идущего сразу послеh2внутри статьи. - Селектор потомков — общий цвет ссылок внутри
nav. - Группировка — единый
font-familyдля всех заголовков (h1,h2,h3). - Селектор атрибута — красный цвет для ссылок с
target="_blank"(добавь такую ссылку вfooter).
- Задай
bodyбазовыйcolorиfont-family— убедись, что все параграфы унаследовали эти значения без явного указания. - Создай класс
.note, переопределяющий цвет текста параграфа — примени его к одному из параграфов и убедись, что переопределение сработало. - Создай конфликт специфичности:
article p { color: green; }и#special p { color: blue; }. Присвой одной из статейid="special"и убедись, что у параграфов внутри именно неё текст синий, а не зелёный.
Собери законченную страницу зоомагазина:
<header>с заголовком «Животные» по центру страницы и навигацией из трёх ссылок («Главная», «Каталог», «Контакты») в одну строку, тоже по центру.<main>с двумя<section>: в первой — картинка кота слева, заголовок «Кошки» и описание справа; во второй — заголовок «Собаки» и описание слева, картинка справа (порядок блоков зеркально меняется). Используйdisplay: inline-blockилиfloatдля расположения картинки и текста рядом.<footer>с телефоном, email и текстом «Все права защищены» — все три строки по центру, на тёмном или светло-сером фоне.- Задай общий шрифт и цвет текста через
body, чтобы он унаследовался всеми элементами.