Цвета, единицы и переменные
HEX, RGB и HSL, прозрачность, чем rem отличается от px и em, и как собрать палитру на переменных, чтобы тема менялась одним классом.
Что ты научишься делать
- Выберешь подходящую запись цвета и проверишь её на контраст
- Перестанешь ставить px везде подряд и поймёшь, когда нужен rem
- Соберёшь палитру на переменных и переключишь тёмную тему одним классом
#Четыре способа записать цвет
| Запись | Пример | Когда удобна |
|---|---|---|
| Имя | tomato, rebeccapurple | Черновик, быстрая проверка. Всего 148 названий |
| HEX | #ff6347 | Самая привычная. Так цвета отдают дизайнеры |
| RGB | rgb(255 99 71) | Когда нужна прозрачность или цвет считается в коде |
| HSL | hsl(9 100% 64%) | Когда нужно сделать «то же самое, но темнее» |
HEX — три пары шестнадцатеричных цифр: красный, зелёный, синий. #ff6347 — это много красного, немного зелёного, чуть синего. Короткая форма #f64 раскрывается в #ff6644.
HSL устроен по-человечески: тон (0–360 по цветовому кругу), насыщенность (0–100 %) и светлота (0–100 %). Главное его достоинство — из него легко получить родственные цвета: тот же тон, другая светлота.
#Прозрачность
/* современная запись: через слэш */background: rgb(101 68 224 / 0.15);background: hsl(262 72% 57% / 0.15);/* восемь цифр в HEX: последние две — прозрачность */background: #6544e026;/* opacity делает прозрачным ВЕСЬ элемент вместе с текстом */opacity: 0.15;#Единицы измерения
Пикселей недостаточно. Разные единицы привязаны к разным вещам, и от выбора зависит, как страница поведёт себя при увеличении шрифта или на другом экране.
| Единица | От чего считается | Где применять |
|---|---|---|
px | Ни от чего. Фиксированная величина | Рамки, тени, мелкие детали |
rem | От размера шрифта в html | Шрифты, отступы, размеры блоков |
em | От размера шрифта самого элемента | Отступы внутри компонента, зависящие от его текста |
% | От соответствующего размера родителя | Ширина колонок, картинок |
vw / vh | От ширины и высоты окна | Полноэкранные блоки, крупные заголовки |
ch | От ширины символа «0» | Ширина текстовой колонки: max-width: 68ch |
fr | Доля свободного места в гриде | Только внутри CSS Grid |
#Почему rem, а не px
В браузере есть настройка «размер шрифта». Ей пользуются люди со слабым зрением — по умолчанию там 16 пикселей, но можно поставить 20 или 24.
Размеры в px эту настройку игнорируют: текст останется мелким. Размеры в rem пересчитаются автоматически.
Считать просто: 1rem = 16px при стандартных настройках. 24px — это 1.5rem, 8px — 0.5rem.
em считается от шрифта самого элемента и поэтому умеет накапливаться. Вложил список в список, у обоих font-size: 0.9em — второй уровень станет 0.81 от исходного, третий 0.73. Иногда это ровно то, что нужно; чаще — источник загадочных багов.
#Переменные
Один и тот же фиолетовый в файле встречается сорок раз. Дизайнер просит сделать его чуть темнее — сорок правок и обязательно одна пропущенная.
Пользовательские свойства (их же называют CSS-переменными) решают это. Объявляются с двух дефисов, читаются через var().
:root { --accent: #6544e0; --accent-dark: #5334cf; --text: #16181d; --bg: #ffffff; --radius: 12px; --gap: 1rem;}.btn { padding: var(--gap); color: var(--bg); background: var(--accent); border-radius: var(--radius);}.btn:hover { background: var(--accent-dark);}:root — это тот же html, только с чуть большим весом. Переменные, объявленные там, видны всей странице: они наследуются.
У var() есть второй аргумент — запасное значение на случай, если переменная не задана: var(--gap, 16px).
#Тёмная тема одним классом
Вот ради чего всё затевалось. Если весь файл пользуется переменными, для смены темы достаточно переопределить их значения.
Где спотыкаются почти все
Все размеры в пикселях
Почему Страница игнорирует настройку размера шрифта в браузере. Людям со слабым зрением приходится увеличивать масштаб всей страницы вместе с картинками.
Как надо Шрифты и отступы — в rem. Пиксели оставь рамкам и теням.
opacity вместо прозрачного фона
Почему Полупрозрачным становится и текст: он теряет контраст и перестаёт читаться.
Как надо Прозрачность задавай прямо в цвете: background: rgb(0 0 0 / .5).
Переменные объявлены в середине файла
Почему Переменная работает только для элемента, где объявлена, и его потомков. Объявишь внутри .card — снаружи её не будет.
Как надо Общая палитра — в :root, в самом верху файла.
Цвета подобраны на глаз, контраст не проверен
Почему Светло-серый на белом красиво выглядит в редакторе и не читается на телефоне в солнечный день.
Как надо Проверяй пару «текст — фон» на 4.5 : 1. Лаборатория цвета выше считает это за тебя.
- HEX hexadecimal color
- Запись цвета шестнадцатеричными числами:
#6544e0. - HSL hue, saturation, lightness
- Запись через тон, насыщенность и светлоту. Удобна для оттенков одного цвета.
- rem root em
- Единица, равная размеру шрифта корневого элемента. По умолчанию 16px.
- Пользовательское свойство custom property
- Переменная CSS: объявляется через
--имя, читается черезvar(). - Контраст contrast ratio
- Отношение яркостей текста и фона. Минимум 4.5 : 1 для обычного текста.
Проверь себя
1rem = 16px по умолчанию, значит 1.5rem = 24px. Но если человек увеличил шрифт в настройках, пересчитается и это.
Из-за привязки к своему элементу <code>em</code> умеет накапливаться при вложенности — иногда это полезно, чаще неожиданно.
<code>opacity</code> и <code>filter</code> делают прозрачным весь элемент вместе с текстом. Прозрачность в цвете затрагивает только фон.
<code>:root</code> — корень документа. Объявленные там переменные наследуются всеми элементами.
Приём делает 1rem равным 10px «для удобства счёта», но заодно обесценивает настройку, ради которой rem и нужен.
Задание
Палитра на переменных и тёмная тема
Перед тобой карточка, где цвета вписаны напрямую. Переделай её:
- объяви в
:rootпеременные--bg,--textи--accent; - используй их в правилах вместо конкретных цветов;
- добавь правило
.dark, которое переопределяет эти три переменные на тёмные; - размеры шрифта задай в
rem, а не вpx.
Класс dark уже стоит на второй карточке — если всё сделано верно, она станет тёмной.
Подсказка 1
Начни так: :root { --bg: #ffffff; --text: #16181d; --accent: #6544e0; }
Подсказка 2
Дальше замени значения: background: var(--bg); color: var(--text);
Подсказка 3
Тёмная тема — это только новые значения: .dark { --bg: #10141f; --text: #e8eaf2; --accent: #b9a5ff; }
Показать решение
<article class="card"> <h2 class="card__title">Светлая карточка</h2> <p class="card__text">Цвета берутся из переменных.</p></article><article class="card dark"> <h2 class="card__title">Тёмная карточка</h2> <p class="card__text">Те же правила, другие значения переменных.</p></article>:root { --bg: #ffffff; --text: #16181d; --accent: #6544e0;}.dark { --bg: #10141f; --text: #e8eaf2; --accent: #b9a5ff;}.card { max-width: 300px; margin-bottom: 12px; padding: 1rem; color: var(--text); background: var(--bg); border-radius: 12px;}.card__title { margin: 0 0 0.5rem; font-size: 1.25rem; color: var(--accent);}.card__text { margin: 0; font-size: 0.875rem;}