Перейти к содержанию
Innovialabs

Что такое CSS: селекторы, каскад и специфичность

Основы3 мин

Коротко

CSS — язык оформления: селектор выбирает элементы, правило задаёт стили, а при конфликте побеждает объявление с более высокой специфичностью или, при равенстве, последнее в коде.

Что такое CSS и как он работает

CSS (Cascading Style Sheets) описывает, как выглядят элементы HTML: цвета, шрифты, отступы, расположение. HTML отвечает за структуру, CSS — за внешний вид.

Каждое правило состоит из селектора и объявлений:

p {
  color: #333;
  line-height: 1.6;
}

p — селектор (все абзацы), color: #333 — объявление «свойство: значение». Браузер читает HTML, строит дерево элементов, находит для каждого все подходящие правила и вычисляет итоговые стили.

Основные селекторы

СелекторПримерЧто выбирает
По тегуpВсе абзацы
По классу.cardЭлементы с class="card"
По id#logoЭлемент с id="logo"
По атрибуту[type="email"]Поля с этим типом
Потомок.card pАбзацы внутри .card
Прямой потомокul > liТолько дочерние li
Псевдоклассa:hoverСсылка под курсором

На практике основа вёрстки — классы. Они переиспользуются и не создают проблем со специфичностью.

Каскад: что делать, если правил несколько

Одному элементу часто подходит несколько правил с одинаковым свойством. Браузер решает конфликт по порядку:

  1. Источник и важность. Стили автора сайта перекрывают стили браузера по умолчанию. !important поднимает приоритет объявления.
  2. Специфичность. Более точный селектор побеждает.
  3. Порядок в коде. При равной специфичности побеждает правило, объявленное позже.
.title { color: blue; }
.title { color: red; } /* победит: объявлено позже */

Специфичность простыми словами

Специфичность считается как три числа: id — классы — теги.

СелекторСпецифичность
p0-0-1
.card p0-1-1
.card .title0-2-0
#main .title1-1-0

Сравнение идёт слева направо: один id сильнее любого количества классов. К «классам» относятся также атрибуты и псевдоклассы, к «тегам» — псевдоэлементы вроде ::before. Инлайн-стиль style="..." сильнее любого селектора.

<p id="intro" class="lead">Текст</p>
#intro { color: green; } /* 1-0-0, победит */
.lead  { color: blue; }  /* 0-1-0 */
p      { color: gray; }  /* 0-0-1 */

Наследование

Часть свойств наследуется от родителя: color, font-family, font-size, line-height. Поэтому шрифт достаточно задать на body.

Другие свойства не наследуются: margin, padding, border, background, width. Принудительно унаследовать значение можно через inherit:

button { font: inherit; }

Блочная модель

Каждый элемент — прямоугольник из четырёх слоёв: content (содержимое), padding (внутренний отступ), border (рамка), margin (внешний отступ).

По умолчанию width задаёт только ширину содержимого, а padding и border добавляются сверху. Поэтому блок width: 300px; padding: 20px на деле занимает 340px. Большинство проектов меняют это поведение:

*, *::before, *::after {
  box-sizing: border-box;
}

Теперь width включает padding и border, и размеры считать проще.

Частые ошибки

  • Борьба через !important. Это временно гасит конфликт, но следующий !important придётся перебивать снова. Лучше упростить селекторы.
  • Стилизация по id. Высокая специфичность мешает потом переопределять стили.
  • Длинные цепочки вроде .page .content .list .item a. Они хрупкие и зависят от разметки.
  • Забытый box-sizing, из-за которого блоки не помещаются в сетку.

Понять, какое правило применилось, помогает вкладка Styles в DevTools: перечёркнутые объявления проиграли каскад. Подробный справочник — на MDN.

Частые вопросы

Обычно в отдельном файле, подключённом через <link rel="stylesheet">. Так стили кешируются и переиспользуются на всех страницах. Инлайн-стили оставьте для редких точечных случаев.

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.