Специфичность, каскад, наследование
Что такое каскад
Каскад — механизм, решающий, какое правило применить, если их несколько.
Порядок принятия решения:
- Важность —
!importantvs обычное. - Источник — автор, пользователь, браузер.
- Специфичность — насколько «точный» селектор.
- Порядок — последнее в файле.
Правило: чем ниже уровень — тем чаще используется.
Специфичность
Веса:
- Inline-стиль —
1000. - ID —
100. - Класс, атрибут, псевдокласс —
10. - Тег, псевдоэлемент —
1. - Универсальный
*—0.
Пример:
p /* 0-0-1 */
.text /* 0-1-0 */
#main /* 1-0-0 */
.card .title /* 0-2-0 */
nav ul li a /* 0-0-4 */
#main .card a:hover /* 1-2-1 */
Правило: сравнивать слева направо — 1-0-0 > 0-99-99.
Как считать
Формула: (a, b, c)
a— количество ID.b— классов, атрибутов, псевдоклассов.c— тегов и псевдоэлементов.
Практика:
/* 0,0,1 */
p { }
/* 0,1,0 */
.button { }
/* 0,1,1 */
p.button { }
/* 0,1,2 */
p.button::before { }
/* 1,0,0 */
#header { }
/* 1,1,0 */
#header .logo { }
/* 1,2,3 */
#main .card .title span a:hover::before { }
Inline-стили
<p style="color: red">Текст</p>
Специфичность: 1,0,0,0 — выше всего, кроме !important.
Правило: inline — не для постоянного оформления. Только динамика от JS.
!important
p { color: red !important; }
Что делает: перебивает всё, кроме ещё более важного.
Когда использовать:
- Utility-классы (Tailwind, Bootstrap утилиты).
- Override сторонних виджетов (без доступа к их CSS).
- Печать (
@media print).
Правило: не использовать для обычных стилей. Признак плохой архитектуры.
Каскад источников
Порядок важности:
- Браузерные стили — user agent.
- Пользовательские — настройки пользователя в браузере.
- Авторские — ваши стили.
- Авторские
!important. - Пользовательские
!important. - Браузерные
!important.
Что важно: !important в пользовательских стилях перебивает ваши. Это для доступности.
Порядок в файле
При равной специфичности побеждает последнее:
p { color: blue; }
p { color: red; } /* победит */
С подключением файлов:
<link href="a.css">
<link href="b.css"> <!-- перебивает a.css при равной специфичности -->
Правило: порядок = приоритет.
Наследование
Наследование — свойства, которые передаются от родителя к потомку.
Наследуемые:
colorfont-familyfont-sizefont-weightline-heighttext-alignvisibilitycursorlist-style
НЕ наследуемые:
marginpaddingborderbackgroundwidth/heightdisplayposition
Правило: задали color родителю — все потомки наследуют.
inherit, initial, unset, revert
.child {
color: inherit; /* взять у родителя */
color: initial; /* дефолтное значение */
color: unset; /* наследуемое — inherit, нет — initial */
color: revert; /* сбросить до браузерного */
}
Когда использовать:
inherit— вернуть наследуемое поведение (например, кнопке от родителя).initial— вернуть дефолт свойства.unset— универсальный сброс.revert— сбросить до браузерного стиля.
Практика: all: unset; — сбросить все свойства элемента.
Наследование форм
Проблема: input не наследует font-family от body:
body { font-family: sans-serif; }
input { /* шрифт — системный, не sans-serif */ }
Решение:
input, button, textarea, select {
font: inherit;
color: inherit;
}
Правило: всегда сбрасывать формы до наследования.
Дефолтные стили браузера
Каждый браузер применяет свои стили (user-agent stylesheet).
Примеры:
h1— крупный и жирный.p— отступы сверху и снизу.ul— маркеры и отступ слева.a— синий и подчёркнутый.button— серый с рамкой.
Проблема: разные браузеры — разные дефолты.
Решение: CSS Reset или Normalize.
CSS Reset
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
img, picture, svg, video {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
Что даёт: единое поведение во всех браузерах.
Normalize.css
Альтернатива Reset. Не обнуляет всё, а приводит к единому виду.
Подключение:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/normalize.css">
Что делает:
- Исправляет баги старых браузеров.
- Унифицирует дефолты.
- Не ломает полезные стили (например, курсив em).
Правило: для нового проекта — современный Reset. Для legacy — Normalize.
Пример: каскад в действии
/* Специфичность 0,0,1 */
p { color: black; }
/* Специфичность 0,1,0 — побеждает */
.text { color: blue; }
/* Специфичность 0,1,1 — побеждает */
p.text { color: green; }
/* Специфичность 0,2,0 — побеждает */
.text.highlight { color: red; }
/* Специфичность 1,0,0 — побеждает */
#main { color: purple; }
HTML:
<p id="main" class="text highlight">Цвет: purple</p>
Как избежать проблем
Правила:
- Не использовать ID для стилей.
- Максимум 3 уровня вложенности селекторов.
- BEM-нейминг —
.block__element--modifier. - Не использовать
!importantбез причины. - Utility-классы для коротких правок.
BEM-пример:
.card { }
.card__title { }
.card__title--large { }
.card--featured { }
Что даёт: плоская структура, предсказуемая специфичность.
Инструменты
DevTools:
- Elements → Styles — все правила на элементе.
- Зачёркнутое — перезаписано.
- Computed — итоговые значения.
- Показать специфичность — в новых браузерах.
Специфичность-калькуляторы:
- specificity.keegan.st
- polistat.github.io/specificity
Практика
1. Проверьте каскад:
p { color: blue; }
.text { color: red; }
#first { color: green; }
<p id="first" class="text">Какой цвет?</p>
Ответ: green (ID побеждает).
2. Добавьте inline:
<p id="first" class="text" style="color: orange">Какой цвет?</p>
Ответ: orange (inline побеждает).
3. Сбросьте стили и посмотрите дефолты.
4. Проверьте наследование color, font-family.
Частые ошибки
1. !important для всего:
color: red !important;
Решение: починить специфичность.
2. ID для стилей:
#header { ... }
Решение: классы.
3. Глубокая вложенность:
.a .b .c .d .e .f { }
Решение: BEM или короткие.
4. Стили форм не сброшены:
input не наследует font-family
Решение: input, button { font: inherit; }.
5. Не понимать порядок:
/* Ожидание: работает первое */
Решение: последнее побеждает.
6. Reset ломает доступность:
/* Убрали focus у ссылок */
a:focus { outline: none; }
Решение: :focus-visible.
7. Забыть про дефолты:
h1 жирный по умолчанию
Решение: Reset.
8. Наследование в <p> с <div>:
<p><div>...</div></p> <!-- невалидно -->
Решение: правильная вложенность.
Итог
- Каскад — порядок применения.
- Специфичность —
(id, class, tag). - Inline > ID > класс > тег.
!important— исключение, не правило.- Наследование — только часть свойств.
- Формы не наследуют — сбросить.
- Reset / Normalize — для единообразия.
- BEM — плоские селекторы.
- DevTools — показать каскад.
Дальше — цвета, единицы, шрифты, текст.