Как выбрать элементы и почему применилось не то правило, которое вы ждали
Стили пишут в отдельном файле .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 из файлов на своём сервере, а не со стороннего сервиса: тогда сайт не зависит от его доступности.
| Селектор | Выбирает |
|---|---|
p | Все элементы <p> |
.price | Элементы с class="price"; классов у элемента может быть несколько: class="price sale" |
#order | Элемент с id="order"; id на странице уникален |
nav a | a где угодно внутри nav (потомки) |
nav > a | a, непосредственно вложенные в nav (дети) |
h1, h2 | И h1, и h2 |
li.new | li с классом 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), по тегу — слишком широки.
Когда к элементу подходят несколько правил с одним свойством, браузер выбирает победителя по каскаду: сначала по специфичности селектора, при равенстве — побеждает правило, записанное позже.
<!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: перечёркнутое объявление и есть проигравшее, а рядом видно, кто его перебил.Часть свойств элемент получает от родителя, если не задано своё значение: наследуются свойства текста — 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; } — кнопки и поля форм по умолчанию свой шрифт не наследуют.
| Единица | Относительно чего | Для чего |
|---|---|---|
px | Пиксель экрана (с учётом масштаба) | Рамки, тени, мелкие отступы |
rem | Размер шрифта корневого элемента html (по умолчанию 16px) | Размеры шрифтов и отступов |
em | Размер шрифта текущего элемента | Отступы, которые растут вместе с текстом кнопки |
% | Размер родителя | Ширина колонок |
vw, vh | 1 % ширины / высоты окна | Полноэкранные блоки |
Разница между 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). Светло-серый текст на белом — частая причина жалоб.
Пользовательские свойства (переменные) хранят повторяющиеся значения дизайна: фирменный цвет, радиус скругления, отступы. Объявляются с двумя дефисами, читаются функцией 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, и кнопка с меткой внутри поменяли цвет без отдельных правил.
body, затем элементы, затем компоненты (кнопки, карточки), затем разделы страниц..price, .card, .btn-primary, а не .red-bold — завтра цена станет синей..menu li — нормально, body div#main ul.menu > li a — нет.style.css?v=2.<link>; правило = селектор + { свойство: значение; }id и атрибут style слишком сильны!important — крайняя мераrem, em умножается при вложении; контраст текста не ниже 4,5 : 1--имя на :root