Модуль 04 — CSS: селекторы и каскад

Как выбрать элементы и почему применилось не то правило, которое вы ждали

Прогресс курса Модуль 4 из 9

Что вы освоите в этом модуле

01

Подключение и синтаксис

Стили пишут в отдельном файле .css и подключают в <head> элементом <link>. Один файл обслуживает все страницы сайта: поменяли цвет заголовков — поменялся везде, а браузер загружает файл один раз и берёт из кэша.

/* Общие стили сайта кафе */
body {
    font-family: Arial, "Helvetica Neue", sans-serif;
    color: #333;
    line-height: 1.5;
}

h1 {
    color: #1967d2;
    font-size: 2rem;
}

.price {
    font-weight: bold;
    color: #c62828;
}
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Меню</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Меню кафе «Нева»</h1>
    <p>Капучино — <span class="price">220 ₽</span></p>
    <p>Сырники — <span class="price">310 ₽</span></p>
</body>
</html>
Результат в браузере
Синий заголовок «Меню кафе «Нева»» шрифтом без засечек и две строки меню, цены выделены красным жирным

Правило CSS — селектор (к каким элементам) и блок объявлений в фигурных скобках: свойство: значение;. Комментарий — /* … */.

СпособПримерКогда
Внешний файл<link rel="stylesheet" href="style.css">Всегда, для стилей сайта
Элемент <style> в head<style> h1 { … } </style>Примеры, одностраничные демо
Атрибут style<p style="color: red">Почти никогда: не переиспользуется и перебивает файл стилей

Шрифт задают списком: font-family: Arial, "Helvetica Neue", sans-serif — браузер берёт первый установленный, последний элемент — общее семейство (sans-serif — без засечек, serif — с засечками, monospace — моноширинный). Свои шрифты подключают правилом @font-face из файлов на своём сервере, а не со стороннего сервиса: тогда сайт не зависит от его доступности.

02

Селекторы

СелекторВыбирает
pВсе элементы <p>
.priceЭлементы с class="price"; классов у элемента может быть несколько: class="price sale"
#orderЭлемент с id="order"; id на странице уникален
nav aa где угодно внутри nav (потомки)
nav > aa, непосредственно вложенные в nav (дети)
h1, h2И h1, и h2
li.newli с классом new
input[type="email"]Элементы с атрибутом и значением
a:hover, :focus, :nth-child(odd)Псевдоклассы — состояние или положение: под указателем, в фокусе, нечётный по счёту
::before, ::afterПсевдоэлементы — добавленное содержимое до или после
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Селекторы</title>
    <style>
        body { font-family: Arial, sans-serif; }
        nav a { color: #1967d2; text-decoration: none; }
        nav > a:hover { text-decoration: underline; }
        .menu li:nth-child(odd) { background: #eef3fb; }
        .menu li.new::after { content: " — новинка"; color: #2e7d32; }
        input[type="email"] { border: 2px solid #1967d2; }
        #order { font-weight: bold; }
    </style>
</head>
<body>
    <nav><a href="#">Меню</a> · <a href="#">Контакты</a></nav>
    <ul class="menu">
        <li>Капучино</li>
        <li class="new">Раф с лавандой</li>
        <li>Американо</li>
        <li>Чай</li>
    </ul>
    <p id="order">Заказ по почте:</p>
    <input type="email" placeholder="you@example.ru" aria-label="Почта">
</body>
</html>
Результат в браузере
Две ссылки навигации, первая подчёркнута под указателем мыши; список напитков с голубым фоном у нечётных строк и зелёной припиской «— новинка» у второго пункта; жирный абзац и поле почты в синей рамке

Снимок сделан с указателем мыши над первой ссылкой — сработал :hover. Текст «— новинка» добавлен псевдоэлементом ::after: в HTML его нет, поэтому для важного содержимого этот приём не используют. Оформляйте через классы: .menu, .price. Селекторы по id слишком сильны (раздел 03), по тегу — слишком широки.

03

Каскад и специфичность

Когда к элементу подходят несколько правил с одним свойством, браузер выбирает победителя по каскаду: сначала по специфичности селектора, при равенстве — побеждает правило, записанное позже.

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Специфичность</title>
    <style>
        body { font-family: Arial, sans-serif; }
        p { color: gray; }
        .note { color: green; }
        #main p { color: blue; }
        p { color: red; }
    </style>
</head>
<body>
    <div id="main">
        <p class="note">Какого я цвета?</p>
    </div>
    <p class="note">А я?</p>
    <p>А я?</p>
</body>
</html>
Результат в браузере
Три строки: первая синяя, вторая зелёная, третья красная

Специфичность считают тремя числами: (количество id, количество классов, атрибутов и псевдоклассов, количество тегов). Сравнивают слева направо, как номера версий.

СелекторСпецифичность
p(0, 0, 1)
.note(0, 1, 0)
#main p(1, 0, 1)
атрибут style="…"сильнее любого селектора

Первый абзац синий: #main p с id сильнее всех. Второй — зелёный: .note сильнее p, хотя p { color: red } записано позже — порядок решает только при равной специфичности. Третий — красный: два правила p равны, побеждает последнее.

color: red !important перебивает всё, включая атрибут style. Это кувалда: перебить её можно только другим !important, и стили превращаются в гонку. Если правило «не применяется», откройте F12 → Styles: перечёркнутое объявление и есть проигравшее, а рядом видно, кто его перебил.
04

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

Часть свойств элемент получает от родителя, если не задано своё значение: наследуются свойства текста — color, font-family, font-size, line-height. Свойства блока — рамки, отступы, фон, размеры — не наследуются.

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Наследование</title>
    <style>
        .card {
            font-family: Georgia, serif;
            color: #6a1b9a;
            border: 2px solid #6a1b9a;
            padding: 8px;
        }
    </style>
</head>
<body>
    <div class="card">
        Карточка
        <p>Абзац внутри: шрифт и цвет унаследованы, рамки нет.</p>
    </div>
</body>
</html>
Результат в браузере
Фиолетовая рамка вокруг карточки; слово «Карточка» и абзац внутри набраны фиолетовым шрифтом с засечками, у абзаца своей рамки нет

Поэтому шрифт и цвет текста задают один раз у body — и они действуют на всей странице. Значение inherit заставляет унаследовать любое свойство: button { font: inherit; } — кнопки и поля форм по умолчанию свой шрифт не наследуют.

05

Единицы и цвета

ЕдиницаОтносительно чегоДля чего
pxПиксель экрана (с учётом масштаба)Рамки, тени, мелкие отступы
remРазмер шрифта корневого элемента html (по умолчанию 16px)Размеры шрифтов и отступов
emРазмер шрифта текущего элементаОтступы, которые растут вместе с текстом кнопки
%Размер родителяШирина колонок
vw, vh1 % ширины / высоты окнаПолноэкранные блоки

Разница между em и rem видна при вложении:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Единицы</title>
    <style>
        body { font-family: Arial, sans-serif; }
        .em  { font-size: 1.2em; }
        .rem { font-size: 1.2rem; }
    </style>
</head>
<body>
    <div class="em">1.2em
        <div class="em">1.2em внутри 1.2em
            <div class="em">и ещё раз — шрифт растёт</div>
        </div>
    </div>
    <div class="rem">1.2rem
        <div class="rem">1.2rem внутри 1.2rem
            <div class="rem">и ещё раз — размер тот же</div>
        </div>
    </div>
</body>
</html>
Результат в браузере
Верхняя группа строк: каждая следующая крупнее предыдущей; нижняя группа: все три строки одного размера

em умножается на каждом уровне: 1,2 × 1,2 × 1,2 ≈ 1,73 от исходного. rem всегда от корня, поэтому предсказуем. Размеры шрифтов задают в rem: если пользователь увеличил шрифт в настройках браузера (так делают люди со слабым зрением), всё увеличится пропорционально, а px эту настройку проигнорирует.

Цвета записывают названием (red), шестнадцатеричным кодом (#1967d2 — красный, зелёный, синий по два знака), функцией rgb(25 103 210) или hsl(215 79% 46%) — тон, насыщенность, светлота; прозрачность — четвёртым значением: rgb(0 0 0 / 50%). Цвет текста должен быть контрастным к фону: для обычного текста соотношение не ниже 4,5 : 1 (требование WCAG и ГОСТ Р 52872). Светло-серый текст на белом — частая причина жалоб.

06

Переменные CSS

Пользовательские свойства (переменные) хранят повторяющиеся значения дизайна: фирменный цвет, радиус скругления, отступы. Объявляются с двумя дефисами, читаются функцией var(). Как и обычные свойства, наследуются — поэтому переопределение на блоке меняет всё внутри него:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Переменные</title>
    <style>
        :root {
            --accent: #1967d2;
            --radius: 8px;
        }
        body { font-family: Arial, sans-serif; }
        .btn {
            background: var(--accent);
            color: white;
            border: none;
            border-radius: var(--radius);
            padding: 8px 16px;
        }
        .tag {
            color: var(--accent);
            border: 1px solid var(--accent);
            border-radius: var(--radius);
            padding: 2px 8px;
        }
        .theme-green { --accent: #2e7d32; }
    </style>
</head>
<body>
    <p><button class="btn">Заказать</button> <span class="tag">новинка</span></p>
    <p class="theme-green"><button class="btn">Заказать</button> <span class="tag">новинка</span></p>
</body>
</html>
Результат в браузере
Две строки: синяя кнопка «Заказать» и синяя метка «новинка»; ниже такие же кнопка и метка зелёного цвета

Переменные на :root (это элемент html) доступны везде. Сменить фирменный цвет сайта — одна правка. Класс .theme-green переопределил --accent, и кнопка с меткой внутри поменяли цвет без отдельных правил.

07

Как организовать стили

Правила, которые экономят время

  • Один файл стилей на сайт; в начале — переменные и общие стили body, затем элементы, затем компоненты (кнопки, карточки), затем разделы страниц.
  • Классы называют по назначению: .price, .card, .btn-primary, а не .red-bold — завтра цена станет синей.
  • Селекторы — по одному классу, как можно короче. .menu li — нормально, body div#main ul.menu > li a — нет.
  • После изменения CSS на работающем сайте браузер может показывать старый файл из кэша. На время разработки — обновление Ctrl+F5; на сайте — версия в адресе: style.css?v=2.

Ключевые выводы модуля

Запомните главное

  • Стили — во внешнем файле через <link>; правило = селектор + { свойство: значение; }
  • Оформляйте через классы; id и атрибут style слишком сильны
  • Конфликт решает специфичность (id, классы, теги), при равенстве — порядок; !important — крайняя мера
  • Свойства текста наследуются, свойства блока — нет
  • Шрифты — в rem, em умножается при вложении; контраст текста не ниже 4,5 : 1
  • Цвета и размеры дизайна — в переменных --имя на :root
Практические задания — на учебном портале. Задания, критерии оценивания, сдача работ и оценки преподавателя — в курсе на portal.nevabit.ru. Учётную запись выдаёт преподаватель.
Модуль 03: Таблицы и формы Все модули Модуль 05: Блочная модель