CSS переменные
CSS-переменные (custom properties) — пользовательские свойства, начинающиеся с
--, которые хранят значения для повторного использования через функциюvar.
Зачем нужно
CSS-переменные устраняют дублирование значений (цвета, размеры, шрифты), упрощают тематизацию и позволяют менять стили динамически через JavaScript. В отличие от переменных Sass, они работают в рантайме и наследуются по DOM-дереву.
Где используется
- Дизайн-токены (цвета, отступы, радиусы, шрифты)
- Тёмная/светлая тема
- Компонентный дизайн (настройка через переменные)
- Динамическое изменение стилей через JS
- Адаптивный дизайн (переопределение переменных в медиа-запросах)
Предпосылки
- Наследование — CSS-переменные наследуются
- Каскад и специфичность — переменные участвуют в каскаде
Синтаксис
Объявление
/* Глобальные переменные — на :root */
:root {
--color-primary: #007bff;
--color-secondary: #6c757d;
--color-success: #28a745;
--color-danger: #dc3545;
--font-family: 'Inter', 'Segoe UI', sans-serif;
--font-size-base: 16px;
--font-size-lg: 1.25rem;
--font-size-sm: 0.875rem;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--border-radius: 8px;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
--transition: 200ms ease-in-out;
}
Использование через var
.button {
background-color: var(--color-primary);
font-family: var(--font-family);
font-size: var(--font-size-base);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
transition: background-color var(--transition);
}
.card {
padding: var(--spacing-lg);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
margin-bottom: var(--spacing-md);
}
Fallback-значения
.element {
/* Если --color-accent не определена, используется #ff6600 */
color: var(--color-accent, #ff6600);
/* Вложенные fallback */
background: var(--bg-custom, var(--bg-default, white));
/* Fallback с другой переменной */
font-size: var(--font-size-custom, var(--font-size-base));
}
Fallback срабатывает только когда переменная не определена. Если переменная определена, но имеет невалидное значение — fallback НЕ сработает, свойство получит
initial.
Область видимости (scope) и наследование
CSS-переменные наследуются по DOM-дереву и могут переопределяться на любом уровне:
:root {
--color: blue;
}
.sidebar {
--color: green; /* Переопределение для .sidebar и всех потомков */
}
.sidebar .title {
color: var(--color); /* green */
}
.main .title {
color: var(--color); /* blue (от :root) */
}
Компонентные переменные
/* Компонент с настраиваемыми переменными */
.alert {
--alert-bg: #f8f9fa;
--alert-color: #333;
--alert-border: #dee2e6;
background: var(--alert-bg);
color: var(--alert-color);
border: 1px solid var(--alert-border);
padding: var(--spacing-md);
border-radius: var(--border-radius);
}
/* Варианты через переопределение переменных */
.alert-success {
--alert-bg: #d4edda;
--alert-color: #155724;
--alert-border: #c3e6cb;
}
.alert-danger {
--alert-bg: #f8d7da;
--alert-color: #721c24;
--alert-border: #f5c6cb;
}
Тёмная тема
:root {
--bg: #ffffff;
--bg-secondary: #f5f5f5;
--text: #1a1a1a;
--text-secondary: #666666;
--border: #e0e0e0;
}
/* Через медиа-запрос */
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--bg-secondary: #2d2d2d;
--text: #e0e0e0;
--text-secondary: #999999;
--border: #404040;
}
}
/* Или через класс (переключается JS) */
.theme-dark {
--bg: #1a1a1a;
--bg-secondary: #2d2d2d;
--text: #e0e0e0;
--text-secondary: #999999;
--border: #404040;
}
/* Стили используют переменные — тема меняется автоматически */
body {
background: var(--bg);
color: var(--text);
}
.card {
background: var(--bg-secondary);
border: 1px solid var(--border);
}
Адаптивные переменные
:root {
--container-width: 1200px;
--font-size-h1: 2.5rem;
--spacing-section: 80px;
}
@media (max-width: 768px) {
:root {
--container-width: 100%;
--font-size-h1: 1.75rem;
--spacing-section: 40px;
}
}
.container {
max-width: var(--container-width);
margin: 0 auto;
}
h1 {
font-size: var(--font-size-h1);
}
section {
padding: var(--spacing-section) 0;
}
Взаимодействие с JavaScript
// Чтение переменной
const root = document.documentElement;
const primary = getComputedStyle(root).getPropertyValue('--color-primary');
// ' #007bff' (с пробелом в начале — trim!)
// Запись переменной
root.style.setProperty('--color-primary', '#ff6600');
// Удаление переопределения
root.style.removeProperty('--color-primary');
// Установка на конкретном элементе
const card = document.querySelector('.card');
card.style.setProperty('--card-bg', 'yellow');
Пример: слайдер меняет размер
<input type="range" id="size-slider" min="12" max="48" value="16">
<p class="demo-text">Текст меняет размер</p>
.demo-text {
font-size: var(--dynamic-size, 16px);
}
document.getElementById('size-slider').addEventListener('input', (e) => {
document.documentElement.style.setProperty(
'--dynamic-size', e.target.value + 'px'
);
});
CSS-переменные vs Sass-переменные
| Особенность | CSS --var |
Sass $var |
|---|---|---|
| Работа | В рантайме | При компиляции |
| Наследование по DOM | Да | Нет |
| Изменение через JS | Да | Нет |
| Медиа-запросы | Переопределяются | Нет |
| Fallback | var(--x, fallback) |
$x: default !default |
| Scope | DOM-дерево | Блок кода |
Частые ошибки
- Невалидное значение не вызывает fallback — свойство становится
initial::root { --size: red; } /* определена, но невалидна для width */ .box { width: var(--size, 100px); /* fallback НЕ сработает! */ /* width получит initial = auto */ } - Нельзя использовать в именах свойств:
/* ОШИБКА */ :root { --prop: margin; } .box { var(--prop): 20px; } /* Так нельзя */ - Нельзя собрать имя свойства или единицу:
:root { --size: 20; } /* ОШИБКА */ .box { width: var(--size)px; } /* Не сработает */ /* ПРАВИЛЬНО */ .box { width: calc(var(--size) * 1px); } - Переменная с пробелом —
getPropertyValueвозвращает значение с пробелом в начале
Практика
- Создать набор дизайн-токенов (цвета, шрифты, отступы) как CSS-переменные
- Реализовать тёмную тему переопределением переменных
- Создать компонент
.buttonс вариантами через переменные - Изменить переменную через JavaScript
- Использовать fallback-значения
Связанные темы
- Блочная область видимости -- let и const — подробнее о функции
var - Наследование — механизм наследования, который используют переменные
- calc() — вычисления с переменными
- Color functions — переменные в цветовых функциях