CSS переменные (custom properties) — var() и :root

CSS переменные (custom properties) позволяют хранить значения один раз и использовать везде. Изменил одну переменную — обновилась вся тема. Плюс их можно читать и изменять через JavaScript.

Вся рубрика CSS: уроки, примеры и справочник по стилям

Синтаксис — объявление и использование

Переменные объявляются с двойного тире --. Используются через функцию var(). Самое распространённое место объявления — :root (глобально).

/* Объявление в :root — доступны везде */
:root {
  --color-primary:   #2563eb;
  --color-secondary: #7c3aed;
  --color-success:   #16a34a;
  --color-danger:    #dc2626;

  --bg-page:   #f9fafb;
  --bg-card:   #ffffff;
  --text-main: #111827;
  --text-muted: #6b7280;

  --font-size-base: 16px;
  --font-weight-bold: 700;

  --border-radius-sm: 6px;
  --border-radius-md: 12px;
  --border-radius-full: 9999px;

  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 32px;
  --spacing-xl: 64px;

  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.1);
}

/* Использование через var() */
.button {
  background: var(--color-primary);
  border-radius: var(--border-radius-sm);
  padding: var(--spacing-sm) var(--spacing-md);
  font-weight: var(--font-weight-bold);
}

.card {
  background: var(--bg-card);
  border-radius: var(--border-radius-md);
  padding: var(--spacing-md);
  box-shadow: var(--shadow-md);
}
Синтаксис CSS variables: объявление custom properties в root и использование через var в кнопке и карточке
Чаще всего CSS переменные объявляют в :root, а компоненты читают их через var(—name).

Запасное значение — второй аргумент var()

/* Если переменная не определена — используется запасное значение */
.text {
  color: var(--color-text, #333);
  /* Если --color-text не задана → #333 */
}

/* Вложенные запасные значения */
.element {
  background: var(--bg-custom, var(--bg-card, white));
  /* Пробует --bg-custom, потом --bg-card, потом white */
}

/* Проверка наличия переменной */
.fallback {
  font-size: var(--fs-custom, 1rem);
}
Fallback значение в CSS var: bg-custom отсутствует, bg-card найден, white как запасной вариант
Второй аргумент var() работает как fallback: если переменная не задана, используется запасное значение.

Область видимости — локальные переменные

Переменные подчиняются каскаду CSS — дочерние элементы наследуют переменные родителей. Можно переопределять переменные для конкретного компонента.

/* :root — глобальные */
:root { --accent: #2563eb; }

/* Переопределение в компоненте */
.card-green {
  --accent: #16a34a;  /* только для этой карточки */
}

.card-red {
  --accent: #dc2626;
}

/* Оба используют одинаковый CSS, но разные цвета */
.card .badge {
  background: var(--accent);  /* будет синим, зелёным или красным */
}

/* Локальные переменные компонента */
.button {
  --btn-color: var(--color-primary);
  --btn-padding: 10px 24px;
  --btn-radius: 8px;

  background: var(--btn-color);
  padding: var(--btn-padding);
  border-radius: var(--btn-radius);
}

.button.large {
  --btn-padding: 14px 32px;  /* только изменяем то что нужно */
}

.button.danger {
  --btn-color: var(--color-danger);
}
Область видимости CSS variables: root accent и локальное переопределение переменной в карточках
CSS переменные подчиняются каскаду: компонент может локально переопределить токен и изменить только свою ветку.

Тёмная тема через CSS переменные

Самый элегантный способ реализовать светлую и тёмную тему — переопределить переменные. Все компоненты автоматически переключаются.

/* Светлая тема (по умолчанию) */
:root {
  --bg:           #ffffff;
  --bg-surface:   #f9fafb;
  --bg-hover:     #f3f4f6;
  --text:         #111827;
  --text-muted:   #6b7280;
  --border:       #e5e7eb;
  --shadow:       0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Тёмная тема через атрибут */
[data-theme="dark"] {
  --bg:           #111827;
  --bg-surface:   #1f2937;
  --bg-hover:     #374151;
  --text:         #f9fafb;
  --text-muted:   #9ca3af;
  --border:       #374151;
  --shadow:       0 1px 3px rgba(0, 0, 0, 0.4);
}

/* Тёмная тема через системные настройки */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:           #111827;
    --bg-surface:   #1f2937;
    --text:         #f9fafb;
    --text-muted:   #9ca3af;
    --border:       #374151;
  }
}

/* Все компоненты используют переменные — переключаются автоматически */
body {
  background-color: var(--bg);
  color: var(--text);
}

.card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}

.btn-ghost:hover {
  background: var(--bg-hover);
}
Светлая и темная тема через CSS variables: одни компоненты используют разные значения bg text border shadow
Для тёмной темы достаточно переопределить переменные, а компоненты автоматически прочитают новые значения.

Управление переменными через JavaScript

const root = document.documentElement;

// Получить значение переменной
const primary = getComputedStyle(root).getPropertyValue('--color-primary').trim();
console.log(primary); // "#2563eb"

// Изменить значение переменной
root.style.setProperty('--color-primary', '#dc2626');
// Теперь всё, что использует var(--color-primary), станет красным

// Переключение тёмной темы
const toggleTheme = () => {
  const isDark = document.documentElement.dataset.theme === 'dark';
  document.documentElement.dataset.theme = isDark ? 'light' : 'dark';
  localStorage.setItem('theme', isDark ? 'light' : 'dark');
};

// Восстановить тему при загрузке
const savedTheme = localStorage.getItem('theme') || 'light';
document.documentElement.dataset.theme = savedTheme;

// Динамический акцентный цвет (например, выбор пользователя)
const colorPicker = document.getElementById('accent-color');
colorPicker.addEventListener('input', (e) => {
  root.style.setProperty('--color-primary', e.target.value);
});
Управление CSS variables через JavaScript: color picker меняет color-primary и обновляет карточку
CSS custom properties можно читать и менять через JavaScript: это удобно для тем, настроек и акцентных цветов.

Переменные для каскадных анимаций

/* Задержка анимации через переменную */
.card {
  opacity: 0;
  animation: fadeIn 0.4s ease var(--delay, 0s) forwards;
}

/* Задаём разные задержки на каждой карточке */
.card:nth-child(1) { --delay: 0.0s; }
.card:nth-child(2) { --delay: 0.1s; }
.card:nth-child(3) { --delay: 0.2s; }
.card:nth-child(4) { --delay: 0.3s; }
.card:nth-child(5) { --delay: 0.4s; }

/* Или через inline style в HTML: */
/* <div class="card" style="--delay: 0.1s"> */
CSS переменные для каскадных анимаций: карточки получают разные значения --delay
Через переменную —delay можно задавать разные задержки карточкам, не дублируя animation-свойство.

Полная дизайн-система через CSS переменные

:root {
  /* === ЦВЕТА === */
  /* Primary */
  --clr-primary-50:  #eff6ff;
  --clr-primary-100: #dbeafe;
  --clr-primary-500: #3b82f6;
  --clr-primary-600: #2563eb;
  --clr-primary-900: #1e3a8a;

  /* Нейтральные */
  --clr-gray-50:  #f9fafb;
  --clr-gray-100: #f3f4f6;
  --clr-gray-500: #6b7280;
  --clr-gray-900: #111827;

  /* Статус */
  --clr-success: #16a34a;
  --clr-warning: #d97706;
  --clr-danger:  #dc2626;

  /* === ТИПОГРАФИКА === */
  --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: 'Fira Code', 'Courier New', monospace;

  --text-xs:   0.75rem;    /* 12px */
  --text-sm:   0.875rem;   /* 14px */
  --text-base: 1rem;       /* 16px */
  --text-lg:   1.125rem;   /* 18px */
  --text-xl:   1.25rem;    /* 20px */
  --text-2xl:  1.5rem;     /* 24px */
  --text-3xl:  1.875rem;   /* 30px */
  --text-4xl:  2.25rem;    /* 36px */

  /* === ОТСТУПЫ (кратно 4) === */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-6:  24px;
  --space-8:  32px;
  --space-12: 48px;
  --space-16: 64px;

  /* === СКРУГЛЕНИЯ === */
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-xl:   16px;
  --radius-full: 9999px;

  /* === ТЕНИ === */
  --shadow-xs: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1), 0 4px 6px rgba(0,0,0,0.05);

  /* === АНИМАЦИИ === */
  --duration-fast:   150ms;
  --duration-normal: 250ms;
  --duration-slow:   400ms;
  --ease-default:    cubic-bezier(0.4, 0, 0.2, 1);
}
Полная дизайн система через CSS variables: colors typography spacing radius shadows motion
CSS переменные масштабируются до дизайн-системы: цвета, шрифты, отступы, радиусы, тени и motion-токены.

Часто задаваемые вопросы о CSS переменных

CSS переменные vs SASS переменные — в чём разница?

SASS переменные ($color: blue) — статические, вычисляются при компиляции, в браузер попадает уже готовый CSS без переменных. CSS custom properties (--color: blue) — живут в браузере, доступны через JavaScript, наследуются и могут меняться динамически. Главное преимущество CSS переменных: можно переключать темы без перезагрузки страницы, переопределять для отдельных компонентов и читать из JavaScript. SASS переменные — только для статических значений в момент сборки.

Можно ли использовать переменные в media queries?

В условиях медиазапроса — нет: @media (max-width: var(--breakpoint)) не работает. Но внутри медиазапроса переменные работают нормально, и можно переопределять переменные в медиазапросе:

:root { --columns: 3; --gutter: 24px; }

@media (max-width: 768px) {
  :root { --columns: 1; --gutter: 16px; }
}

.grid {
  grid-template-columns: repeat(var(--columns), 1fr);
  gap: var(--gutter);
}

Браузерная поддержка CSS custom properties?

CSS переменные поддерживаются всеми современными браузерами (Chrome 49+, Firefox 31+, Safari 9.1+, Edge 15+). Общая поддержка — 97%+ глобально. Единственное исключение — Internet Explorer 11, который не поддерживает CSS custom properties вообще. Если нужна поддержка IE11, используй препроцессоры (SASS/Less) или PostCSS плагины.

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x