CSS переменные (custom properties): практическое руководство для начинающих

CSS переменные (custom properties): практическое руководство для начинающих

CSS переменные (custom properties): практическое руководство для начинающих

Запрос «CSS переменные» стабильно набирает популярность: всё больше разработчиков переходят от жёстко прописанных значений к гибким и масштабируемым стилям. В этом руководстве мы разложим по полочкам, как работать с custom properties, зачем нужны var() и :root, как быстро включить тёмную тему и управлять цветами из JavaScript.

Быстрый старт: объявление и использование

CSS переменные задаются через имя, начинающееся с двойного дефиса, а читаются функцией var().

:root {
  --brand: #6c5ce7;
  --gap: 1rem;
}

.btn {
  background: var(--brand);
  padding: calc(var(--gap) * 1.5) var(--gap);
  border-radius: 8px;
  color: #fff;
}

:root — это корневой селектор документа (обычно html). Значения, объявленные здесь, доступны везде, если их не переопределить ниже по дереву.

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

CSS переменные наследуются. Это удобно для локальной настройки компонентов без пересборки всего дизайна.

.card {
  --card-bg: #ffffff;
  --card-text: #111;
  background: var(--card-bg);
  color: var(--card-text);
  padding: 1rem;
}

.card.is-dark {
  --card-bg: #1e1f25;
  --card-text: #f0f3f7;
}

Переключая модификатор .is-dark, мы меняем только переменные внутри карточки — остальные элементы страницы не затрагиваются.

Тёмная тема за 2 шага

Сделаем базовую тему и переопределим переменные для тёмного режима с помощью атрибута или системных настроек.

:root {
  --bg: #ffffff;
  --fg: #111111;
  --accent: #2f80ed;
}

[data-theme="dark"] {
  --bg: #0f1218;
  --fg: #e7eaf0;
  --accent: #6ab0ff;
}

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

/* Автоподстройка под систему */
@media (prefers-color-scheme: dark) {
  :root { --bg: #0f1218; --fg: #e7eaf0; }
}

Чтобы переключать темы из JS, достаточно менять атрибут на <html>: document.documentElement.dataset.theme = 'dark';

var() с запасным значением и типичные ошибки

Если переменная не определена, используйте второй аргумент var() как фолбэк.

.link {
  color: var(--link, #0066cc);
}
  • Ошибка: забыть единицы измерения внутри переменной. Правильно: --space: 16px; (а не 16).
  • Ошибка: рассчитывать в calc() несопоставимые единицы (например, px + em без нормализации).
  • Ошибка: ожидать, что переменные будут работать в селекторах или медиа-выражениях — нельзя.
  • Гибкие размеры: clamp(), min(), max() + переменные

    Переменные отлично сочетаются с функциями для «резиновой» типографики и отступов.

    :root {
      --fs-base: clamp(1rem, calc(0.95rem + 0.5vw), 1.25rem);
      --container: min(100% - 2rem, 72rem);
    }
    
    body { font-size: var(--fs-base); }
    .wrapper { width: var(--container); margin-inline: auto; }
    

    Важно: CSS переменные нельзя подставлять в условиях @media (например, @media (max-width: var(--bp)) не сработает). Используйте их внутри свойств, но не в селекторах и не в медиа-выражениях.

    JavaScript + CSS переменные: динамические темы и параметры

    Менять значение можно прямо из JS — без пересборки стилей.

    // Установить значение
    document.documentElement.style.setProperty('--brand', '#ff4757');
    
    // Прочитать текущее значение
    const brand = getComputedStyle(document.documentElement)
      .getPropertyValue('--brand').trim();
    console.log(brand);
    
    // Переключение темы
    const root = document.documentElement;
    root.dataset.theme = root.dataset.theme === 'dark' ? 'light' : 'dark';
    

    Такой подход особенно удобен для пользовательских настроек (размер шрифта, контраст, акценты) и визуализации данных (например, динамическая окраска графиков).

    Анимации и плавные переходы с @property

    Чтобы анимировать значения переменных и получать корректные переходы, зарегистрируйте их тип через @property.

    @property --brand-hue {
      syntax: '<number>';
      inherits: false;
      initial-value: 260;
    }
    
    :root { --brand-hue: 260; }
    
    .btn {
      /* hsl() на основе hue-переменной */
      background: hsl(var(--brand-hue) 80% 60%);
      transition: --brand-hue 300ms ease;
    }
    
    .btn:hover { --brand-hue: 330; }
    

    Без @property браузер не знает, как интерполировать значение, и переход может происходить рывком или не происходить вовсе.

    Стратегии именования и структура дизайна

  • Базовые токены: --color-fg, --color-bg, --space-1, --radius-2 — задаются в :root.
  • Семантические токены: --btn-bg, --card-shadow, --link-color — можно переопределять в темах или состояниях.
  • Локальные токены компонента: объявляйте прямо в корневом селекторе компонента (.card, .modal).
  • Проверенный шаблон подключения токенов

    :root {
      /* Базовые (глобальные) */
      --color-fg: #111;
      --color-bg: #fff;
      --color-accent: #2f80ed;
      --space-1: .5rem;
      --space-2: 1rem;
      --radius-2: 8px;
    }
    
    /* Светлая/тёмная темы */
    [data-theme="dark"] {
      --color-fg: #e7eaf0;
      --color-bg: #0f1218;
      --color-accent: #6ab0ff;
    }
    
    /* Компонент */
    .card {
      --card-bg: var(--color-bg);
      --card-fg: var(--color-fg);
      background: var(--card-bg);
      color: var(--card-fg);
      padding: var(--space-2);
      border-radius: var(--radius-2);
      box-shadow: 0 6px 18px rgb(0 0 0 / 8%);
    }
    
    .card--accent { border: 2px solid var(--color-accent); }
    

    Производительность и поддержка

    CSS переменные поддерживаются всеми современными браузерами. Они вычисляются на этапе компоновки, что позволяет экономить на дублировании CSS и упрощает масштабирование. Старайтесь не переопределять слишком много переменных на глубоко вложенных узлах без необходимости — это усложняет дебаг.

    Чек-лист лучших практик

  • Храните базовые токены в :root, а локальные — в компонентах.
  • Используйте семантические имена (не --blue, а --color-accent).
  • Добавляйте фолбэки в var(), особенно для критичных свойств.
  • Типизируйте анимируемые переменные через @property.
  • Не пытайтесь подставлять переменные в селекторах и @media — используйте их только в значениях свойств.
  • Что дальше?

    Освоив CSS переменные, вы получите более чистую архитектуру стилей, простую темизацию и быстрые правки дизайна. Хотите системно натренировать эти навыки на реальном макете с наставником? Загляните в курс: Прокачать вёрстку на практике и собрать сайт с нуля →

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий