ДокументацияCSSCSS переменные (Custom Properties)
Начальный 7 мин чтения

CSS переменные (Custom Properties)

CSS Custom Properties позволяют хранить значения в переменных, переиспользовать их и изменять динамически через JavaScript.

css variablescustom propertiesthemingdark mode

Объявление и использование

CSS-переменные (Custom Properties) объявляются через -- и используются через var():

:root {
  --color-primary: #7c3aed;
  --spacing-md: 16px;
  --border-radius: 8px;
  --font-size-base: 1rem;
}

.button {
  background-color: var(--color-primary);
  padding: var(--spacing-md);
  border-radius: var(--border-radius);
  font-size: var(--font-size-base);
}

:root — псевдокласс, соответствующий <html>. Объявленные здесь переменные доступны глобально.

Значение по умолчанию

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

  font-size: var(--size, var(--fallback-size, 16px));
  /* Вложенные fallback-и */
}

Область видимости

Переменные следуют каскаду CSS — дочерние элементы наследуют переменные родителя:

:root {
  --card-bg: white;
}

.dark-section {
  --card-bg: #1e1e1e;  /* Переопределяем для этого раздела */
}

.card {
  background: var(--card-bg); /* Будет разным в зависимости от контекста */
}

Тёмная тема

:root {
  --bg: #ffffff;
  --text: #111827;
  --border: #e5e7eb;
  --surface: #f9fafb;
}

.dark {
  --bg: #0f172a;
  --text: #f1f5f9;
  --border: #1e293b;
  --surface: #1e293b;
}

body {
  background: var(--bg);
  color: var(--text);
}

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

Переключение темы — просто добавить/убрать класс dark на <html> через JavaScript.

Динамическое изменение через JavaScript

const root = document.documentElement

// Получить значение
const primary = getComputedStyle(root).getPropertyValue('--color-primary')

// Установить значение
root.style.setProperty('--color-primary', '#3b82f6')

// Удалить (вернуть к значению из таблицы стилей)
root.style.removeProperty('--color-primary')

Компонентный подход

/* Дефолтные значения компонента */
.button {
  --btn-bg: #7c3aed;
  --btn-color: white;
  --btn-padding: 8px 16px;
  --btn-radius: 6px;

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

/* Кастомизация через переопределение */
.button.danger {
  --btn-bg: #dc2626;
}

.button.ghost {
  --btn-bg: transparent;
  --btn-color: #7c3aed;
}

/* Кастомизация снаружи */
.my-form .button {
  --btn-bg: #0ea5e9;
}

Расчёты с переменными

:root {
  --base-spacing: 4px;
}

.section {
  padding: calc(var(--base-spacing) * 6); /* 24px */
  margin-bottom: calc(var(--base-spacing) * 8); /* 32px */
}

/* Система шрифтов */
:root {
  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.25rem;
  --text-2xl:  1.5rem;
}

Анимация значений

/* Анимация через изменение переменной */
.progress {
  --progress: 0;
  width: calc(var(--progress) * 100%);
  transition: width 0.3s ease;
}
bar.style.setProperty('--progress', '0.75')

Ограничения

  • CSS-переменные не работают в медиазапросах: @media (min-width: var(--breakpoint)) — не работает
  • Не поддерживаются в url(): background: url(var(--image-path)) — не работает
  • Синтаксис с @property (Houdini) позволяет добавить типизацию и анимацию числовых значений
@property --progress {
  syntax: '<number>';
  initial-value: 0;
  inherits: false;
}