Skip to content

Latest commit

 

History

History
581 lines (434 loc) · 25.9 KB

File metadata and controls

581 lines (434 loc) · 25.9 KB

Урок 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>

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


Расширенные селекторы в CSS

Расширенные селекторы позволяют выбирать элементы не только по имени тега, классу или id, но и в зависимости от их положения в структуре документа — вложенности, соседства — а также объединять несколько селекторов в одно правило.

Селектор потомков — A B

Выбирает все элементы B, которые находятся внутри A на любом уровне глубины, не обязательно как прямые дети.

main div {
  background: #fff8e1;
}

Захватит все div где-нибудь внутри main — будь то прямые дети, внуки или ещё глубже. Будьте аккуратны: descendant-селектор может затронуть больше элементов, чем ожидается, если структура гибкая.

Дочерний селектор — A > B

Выбирает только те B, которые являются прямыми детьми A.

main > article {
  margin-bottom: 24px;
}

Сработает только для article, расположенных непосредственно внутри main. Если article вложен глубже (например, внутри section), правило не сработает — используйте этот вид селектора, когда важно не затрагивать более глубокие уровни вложенности.

Соседний селектор — A + B

Выбирает элемент B, который непосредственно следует за A на том же уровне вложенности.

h2 + p {
  margin-top: 8px;
  color: #333;
}

Применится только к p, который идёт сразу после h2 в том же родителе. Удобно для типичного паттерна «заголовок + первый абзац» — например, чтобы настроить именно ему отступ.

Общий сосед — A ~ B

Выбирает все элементы B, которые идут после A и имеют того же родителя — не обязательно сразу следующие.

h2 ~ p {
  color: #666;
}

Применится ко всем p после h2 в рамках одного родителя, а не только к первому.

Группировка селекторов — A, B, C

Позволяет задать один и тот же набор свойств сразу нескольким селекторам одним правилом.

h1,
h2,
h3 {
  font-family: "Arial", sans-serif;
  color: #222;
}

Селекторы атрибутов — A[атрибут="значение"]

Выбирает элементы по наличию или значению указанного атрибута.

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

Некоторые 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, initial, unset

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

До появления 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 у родителя выравнивает их как строку.

Колонки через inline-block

.columns {
    text-align: center;
}

.column {
    display: inline-block;
    width: 30%;
    margin: 1%;
    background: lightyellow;
    text-align: center;
}

Колонки встают в ряд и автоматически переносятся на новую строку, если ширины экрана не хватает.

Колонки через float

.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

Вопросы для проверки

  1. Что такое семантическая разметка и чем она отличается от разметки через div без классов, объясняющих назначение?
  2. Чем <section> отличается от <article>?
  3. В чём разница между селектором потомков (A B) и дочерним селектором (A > B)?
  4. Чем соседний селектор (A + B) отличается от общего соседа (A ~ B)?
  5. Какие CSS-свойства обычно наследуются от родителя к потомку, а какие — нет? Приведи по два примера каждого вида.
  6. Как рассчитывается специфичность селектора (упрощённо), и какой из трёх селекторов победит: p, .intro p, #main .intro p — если все они конфликтуют для одного и того же элемента?
  7. Что произойдёт, если два CSS-правила имеют одинаковую специфичность и конфликтуют между собой?
  8. Зачем нужен селектор атрибутов, например a[target="_blank"]? Приведи практический сценарий использования.
  9. Почему у margin: 0 auto элемент обязательно должен иметь заданную фиксированную ширину, чтобы центрирование сработало?
  10. Почему при использовании float для колонок часто требуется clear: both у следующего за ними элемента?

Практические задания

Задание 1. От div к семантике

Возьми простую структуру страницы, написанную только через <div> (шапка, основной контент, подвал), и перепиши её на семантические теги: <header>, <main>, <footer>. В <header> добавь <h1> с названием сайта и <nav> с тремя ссылками. В <main> создай два <article>, каждый с заголовком <h2> и текстом. В <footer> укажи email и телефон.


Задание 2. Расширенные селекторы в действии

На основе разметки из Задания 1 напиши CSS, используя каждый из изученных видов селекторов:

  1. Дочерний селектор — рамка для всех article, лежащих прямо внутри main.
  2. Соседний селектор — увеличенный margin-top для абзаца, идущего сразу после h2 внутри статьи.
  3. Селектор потомков — общий цвет ссылок внутри nav.
  4. Группировка — единый font-family для всех заголовков (h1, h2, h3).
  5. Селектор атрибута — красный цвет для ссылок с target="_blank" (добавь такую ссылку в footer).

Задание 3. Наследование и специфичность

  1. Задай body базовый color и font-family — убедись, что все параграфы унаследовали эти значения без явного указания.
  2. Создай класс .note, переопределяющий цвет текста параграфа — примени его к одному из параграфов и убедись, что переопределение сработало.
  3. Создай конфликт специфичности: article p { color: green; } и #special p { color: blue; }. Присвой одной из статей id="special" и убедись, что у параграфов внутри именно неё текст синий, а не зелёный.

Задание 4. Магазин «Животные» — объединяющая практика

Собери законченную страницу зоомагазина:

  1. <header> с заголовком «Животные» по центру страницы и навигацией из трёх ссылок («Главная», «Каталог», «Контакты») в одну строку, тоже по центру.
  2. <main> с двумя <section>: в первой — картинка кота слева, заголовок «Кошки» и описание справа; во второй — заголовок «Собаки» и описание слева, картинка справа (порядок блоков зеркально меняется). Используй display: inline-block или float для расположения картинки и текста рядом.
  3. <footer> с телефоном, email и текстом «Все права защищены» — все три строки по центру, на тёмном или светло-сером фоне.
  4. Задай общий шрифт и цвет текста через body, чтобы он унаследовался всеми элементами.

Предыдущий урок | Следующий урок