
Переменные CSS (также известные как настраиваемые свойства) поддерживаются браузерами почти 4 года. Мне нравится применять их в зависимости от проекта или ситуации. Они очень полезны и просты в использовании, но зачастую фронтенд разработчик неправильно использует или неправильно понимает их.
Основная цель статьи: я хочу иметь место, где собрано все, что я знаю о переменных CSS, чтобы узнать и понять больше. Здесь вы прочитаете обо всем, что должны знать о переменных CSS, включая примеры применения в коде. Вы готовы? Тогда погружаемся.
Введение
Переменные CSS — это значения, определенные в документе CSS с целью переиспользования и уменьшения количества избыточных значений CSS. Простой пример:

.section { border: 2px solid #235ad1; } .section-title { color: #235ad1; } .section-title::before { content: ""; display: inline-block; width: 20px; height: 20px; background-color: #235ad1; }
В этом фрагменте #235ad1 встречается трижды. Представьте, что в большом проекте есть разные файлы CSS и вас попросили изменить какой-то цвет. Лучшее, что вы можете сделать — использовать поиск и замену.
Такое лучше сделать с помощью переменных CSS. Посмотрим, как определять их. Вначале пишется двойной дефис. Определим переменную в :root (то есть в элементе HTML):
:root { --color-primary: #235ad1; } .section { border: 2px solid var(--color-primary); } .section-title { color: var(--color-primary); } .section-title::before { /* Other styles */ background-color: var(--color-primary); }
Не так много кода, и он чище кода выше, не правда ли? Переменная --color-primary глобальная, потому что определена в элементе :root. Но возможно ограничивать область действия переменных.
Именование переменных
Именование CSS не так уж отличается от именования переменных в языках программирования. Корректное имя переменной может содержать латинские буквы и цифры, подчеркивания, тире. Важно упомянуть, что переменные CSS чувствительны к регистру.
/* Valid names */ :root { --primary-color: #222; --_primary-color: #222; --12-primary-color: #222; --primay-color-12: #222; } /* Invalid names */ :root { --primary color: #222; /* Spacings are not allowed */ --primary$%#%$# }
Область видимости
Что полезно в переменных CSS: мы можем указывать область видимости. Принцип аналогичен тому, что и в языках программирования. Возьмем, например, JavaScript:
let element = "cool"; function cool() { let otherElement = "Not cool"; console.log(element); }
Переменная element глобальная, поэтому доступна внутри функции cool(). Однако переменная otherElement доступна только в функции cool(). Применим этот принцип к переменным CSS.
:root { --primary-color: #235ad1; } .section-title { --primary-color: d12374; color: var(--primary-color); }
Переменная --primary-color глобальна и может быть доступна из любого элемента документа. Переопределяя ее в рамках блока объявления .section-title, ее новое значение работает только там. Визуальный пример показывает лучше:

Мы имеем --primary-color, используемую для цвета заголовка раздела. Мы можем настроить цвет для избранных авторов и последнего раздела статьи, когда переопределяем их. То же применимо к переменной --unit. Вот CSS для рисунка выше:
/* Global variables */ :root { --primary-color: #235ad1; --unit: 1rem; } /* Section title default color and spacing */ .section-title { color: var(--primary-color); margin-bottom: var(--unit); } /* Overrding the section title color */ .featured-authors .section-title { --primary-color: #d16823; } /* Overrding the section title color & spacing */ .latest-articles .section-title { --primary-color: #d12374; --unit: 2rem; }
Резервные значения
Резервное значение не означает, что мы обеспечиваем значение для браузера, который не поддерживает CSS. Эту возможность мы можем использовать с помощью переменных CSS. Посмотрите на пример:
.section-title { color: var(--primary-color, #222); }
Обратите внимание: функция var() имеет несколько значений. Второй вариант #222 работает только тогда, когда переменная --primary-color по какой-то причине не определена. Мало того, мы можем вложить var() в другую var().
.section-title { color: var(--primary-color, var(--black, #222)); }
Эта особенность полезна, когда значение зависит от определенного действия. Резервное значение важно предоставить, когда у переменной нет значения.
Примеры использования
Управление размером компонента

Обычное дело — иметь несколько размеров кнопки в дизайн-системе: маленький, средний и большой. Размеры проще описать с помощью переменной CSS.
.button { --unit: 1rem; padding: var(--unit); } .button--small { --unit: 0.5rem; } .button--large { --unit: 1.5rem; }
Изменяя значение --unit внутри области видимости компонента кнопки мы создаем разные варианты кнопки.
Переменные CSS и цвета HSL
HSL — английская аббревиатура: оттенок, насыщенность, яркость.

:root { --primary-h: 221; --primary-s: 71%; --primary-b: 48%; } .button { background-color: hsl(var(--primary-h), var(--primary-s), var(--primary-b)); transition: background-color 0.3s ease-out; } /* Making the background darker */ .button:hover { --primary-b: 33%; }
Обратите внимание, как темнеет кнопка с уменьшением значения переменной —primary-b.
Если хочется узнать больше о цветах в CSS, я написал о них подробную статью .
Пропорциональное изменение размера
Если вы работали с Photoshop, Sketch, Figma или Adobe XD, то у вас может возникнуть идея удерживать клавишу Shift для пропорционального изменения размера элемента. В CSS нельзя сделать такое напрямую, но есть обходной путь с применением переменных CSS.

Предположим, есть иконка, которая должна быть квадратной. Я определил переменную --size и использовал ее как для ширины, так и для высоты.
.icon { --size: 22px; width: var(--size); height: var(--size); }
Вот оно! Теперь вы можете имитировать эффект Shift, изменяя только значение переменной --size. Вы можете узнать больше об этом здесь.
CSS Grid
Переменные CSS могут быть крайне полезны для сеток.

.wrapper { --item-width: 300px; display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr)); grid-gap: 1rem; } .wrapper-2 { --item-width: 500px; }
Благодаря этому мы можем создать полную сеточную систему, гибкую, простую в обслуживании и переиспользуемую. Тот же принцип применим к свойству grid-gap.
.wrapper { --item-width: 300px; --gap: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr)); } .wrapper.gap-1 { --gap: 16px; }

Сохранение наполненных значений
Градиенты CSS
Под наполненными значениями я имею в виду, например, градиент. Когда у вас есть используемые в системе градиент или фон, их можно сохранить в переменной CSS.
:root { --primary-gradient: linear-gradient(150deg, #235ad1, #23d1a8); } .element { background-image: var(--primary-gradient); }
Или сохранить одно значение. Возьмем, к примеру, угол наклона:
.element { --angle: 150deg; background-image: linear-gradient(var(--angle), #235ad1, #23d1a8); } .element.inverted { --angle: -150deg; }

Положение фона
Возможно включить значения в переменную. Это полезно, когда элемент позиционируется в зависимости от контекста.

.table { --size: 50px; --pos: left center; background: #ccc linear-gradient(#000, #000) no-repeat; background-size: var(--size) var(--size); background-position: var(--pos); }
Переключение между темным и светлым режимами
Темный и светлый режимы сейчас востребованы для веб-сайтов как никогда. С помощью переменных CSS мы можем хранить две их версии и переключаться между ними в зависимости от предпочтений пользователя или системных настроек.

:root { --text-color: #434343; --border-color: #d2d2d2; --main-bg-color: #fff; --action-bg-color: #f9f7f7; } /* A class added to the <html> element*/ .dark-mode { --text-color: #e9e9e9; --border-color: #434343; --main-bg-color: #434343; --action-bg-color: #363636; }
Установка значения по умолчанию
Иногда нужно установить переменную CSS с помощью JavaScript . Например, нужно получить высоту расширяемого компонента. Я узнал об этой технике из статьи Майкла Шарнагла.
Переменная --details-height-open пуста. Она добавляется к определенному элементу HTML. Он будет содержать пиксельное значение. Когда по какой-то причине Javascript не работает, важно указать правильное значение по умолчанию или резервное значение.
.section.is-active { max-height: var(--details-height-open, auto); }
Значение auto — это резервное значение на случай сбоя JavaScript и отсутствия переменной CSS --details-height-open.
Управление шириной враппера

Враппер веб-сайта может иметь несколько вариантов. Может быть, вам нужна небольшая обертка для страницы, но большая для другой. В таком случае полезны переменные CSS.
.wrapper { --size: 1140px; max-width: var(--size); } .wrapper--small { --size: 800px; }
Встроенные стили
Переменные CSS со встроенными стилями открывают множество возможностей, о которых вы, возможно, не знали. Об этом я написал статью, но здесь я упомяну некоторые интересные варианты применения. Возможно, такой подход не идеален для реально работающих веб-сайтов, но он может быть полезен при создании прототипов и в тестировании различных идей.
Элементы динамической сетки
Добавляем переменную --item-width внутри атрибута style и все. Такой подход помогает, например, в создании прототипов сеток.
<div class="wrapper" style="--item-width: 250px;"> <div></div> <div></div> <div></div> </div>
.wrapper { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr)); grid-gap: 1rem; }
Аватары пользователей

Полезный вариант применения — определение размеров элементов. Допустим, нужно четыре разных размера аватара пользователя с возможностью контроля размера с помощью только одной переменной.
<img src="user.jpg" alt="" class="c-avatar" style="--size: 1" /> <img src="user.jpg" alt="" class="c-avatar" style="--size: 2" /> <img src="user.jpg" alt="" class="c-avatar" style="--size: 3" /> <img src="user.jpg" alt="" class="c-avatar" style="--size: 4" />
.c-avatar { display: inline-block; width: calc(var(--size, 1) * 30px); height: calc(var(--size, 1) * 30px); }
Проанализируем CSS выше:
- Во-первых, у нас есть
var(--size, 1). Я добавил резервное значение на случай, если оно не добавлено в атрибут style. - Минимальный размер аватара — 30*30 пикселей.
Медиа-запросы
Комбинирование переменных CSS и медиа-запросов очень полезно в настройке переменных, применяемых на всем веб-сайте. Самый простой пример, о котором я думаю, — изменение значения отступов.
:root { --gutter: 8px; } @media (min-width: 800px) { :root { --gutter: 16px; } }
Любой элемент с --gutter, изменит отступ в зависимости от размера области просмотра. Разве это не здорово?
Наследование
Да, переменные CSS наследуются. Если в родительском элементе определена переменная, дочерние элементы наследуют ее. Пример:
<div class="parent"> <p class="child"></p> </div>
.parent { --size: 20px; } .child { font-size: var(--size); }
Элемент .child будет иметь доступ к переменной —size в результате наследования ее от своего родителя. Интересно, правда? Как извлечь из этого пользу? Что ж, вот пример из жизни.

У нас есть группа действий с такими требованиями:
- Возможность изменять размер всех элементов, изменяя только одну переменную.
- Интервал должен быть динамическим (сжиматься при уменьшении размера элемента и увеличиваться при увеличении размера элемента).
<div class="actions"> <div class="actions__item"></div> <div class="actions__item"></div> <div class="actions__item"></div> </div>
.actions { --size: 50px; display: flex; gap: calc(var(--size) / 5); } .actions--m { --size: 70px; } .actions__item { width: var(--size); height: var(--size); }
Обратите внимание, как —size используется для свойства зазора flexbox. Это означает, что интервал может быть динамическим и будет зависеть от переменной --size.
Другой полезный пример — наследование переменных CSS для настройки анимации. Ниже вы видите пример из этой статьи Сандрины Перейры в блоге CSS Tricks.
@keyframes breath { from { transform: scale(var(--scaleStart)); } to { transform: scale(var(--scaleEnd)); } } .walk { --scaleStart: 0.3; --scaleEnd: 1.7; animation: breath 2s alternate; } .run { --scaleStart: 0.8; --scaleEnd: 1.2; animation: breath 0.5s alternate; }
При таком подходе не нужно определять @keyframes дважды. Значения наследуются из .walk и .run.
Как работает валидация переменных CSS
Когда переменная CSS внутри функции var() невалидна, браузер заменяет ее начальным или унаследованным значением в зависимости от свойства.
:root { --main-color: 16px; } .section-title { color: var(--main-color); }
Я использовал 16 пикселей — это значение свойства цвета. Значение неправильное. Поскольку свойство цвета наследуются, вот, что сделает браузер:
- Свойство наследуемо?
- Если да, есть ли у родителя это свойство?
- Да: значение наследуется
- Нет: устанавливается по умолчанию
- Если нет, устанавливается начальное значение
Диаграмма показывает работу браузера:

Некорректное вычисленное значение
Вышеупомянутое технически называется некорректное вычисленное значение. Это происходит, когда var() ссылается на переменную CSS ее начальным значением или использует допустимую переменную CSS с недопустимым значением свойства.
Посмотрим на пример, о котором я узнал из этой статьи пользователя Lea Verou.
.section-title { top: 10px; top: clamp(5px, var(--offset), 20px); }
Когда браузер не поддерживает функцию clamp(), будет ли top: 10px работать как резервное значение. Короткий ответ — нет. Причина в том, что когда браузер обнаружил невалидное значение, он уже отбросил другие значения. Это означает, что top: 10px будет игнорироваться
Согласно спецификации CSS:
Концепция некорректного вычисленного значения существует потому, что переменные не могут «не работать сразу», как в случае синтаксических ошибок, поэтому к тому времени, когда агент пользователя понимает, что значение свойства недопустимо, он уже отбрасывает другие каскадные значения.
То есть когда вы хотите использовать не распространенную функцию CSS и в ней есть переменная CSS, работайте с @supports. Вот как Леа Веру использовала эту технику в своей статье:
@supports (top: max(1em, 1px)) { #toc { top: max(0em, 11rem — var(--scrolltop) * 1px); } }
Интересные находки
URL как значение
Возможно, вы не можете контролировать все ресурсы на веб-странице. Некоторые из них должны размещаться в интернете. В этом случае вы можете сохранить URL-адрес ссылки в переменной CSS.
:root { --main-bg: url(«https://example.com/cool-image.jpg»); } .section { background: var(--main-bg); }
Можно задаться вопросом: можно ли интерполировать CSS-переменные с помощью url(). Посмотрим на пример:
:root { --main-bg: «https://example.com/cool-image.jpg»; } .section { background: url(var(--main-bg)); }
Это невозможно: var(--main-bg) рассматривается как сам URL, который недопустим. К тому моменту, когда браузер вычислит это значение, оно уже не будет действительным и не будет работать, как ожидалось.
Хранение нескольких значений
Полезно то, что возможно хранить несколько значений независимо от значения переменной. Если они невалидны, то это должно сработать. Посмотрим на пример:

:root { --main-color: 35, 90, 209; } .section-title { color: rgba(var(--main-color), 0.75); }
В этом примере у нас есть функция rgba(). Значения RGB хранятся в переменной CSS, разделенной запятой. Это может обеспечить гибкость в случае, когда вы хотите настроить прозрачность в зависимости от элемента.
Единственный недостаток — невозможно настроить значение rgba с помощью палитры цветов DevTools. Если это важно для вашего варианта применения или проекта, то вам, возможно, придется пересмотреть использование rgba, как описано выше.
Другой пример — применение этого свойства со свойством background.
:root { --bg: linear-gradient(#000, #000) center/50px; } .section { background: var(--bg); } .section--unique { background: var(--bg) no-repeat; }
У нас есть два раздела. Один из них требует, чтобы фон не повторялся по осям X и Y.
Анимация переменных внутри правила @keyframes
Если вы читали спецификацию для переменных, вы могли прочитать термин animation-tainted — испорченная анимация. Идея в том, что при использовании CSS-переменной внутри правила @keyframes она не может работать в анимации.
<div class="box"></div>
.box { width: 50px; height: 50px; background: #222; --offset: 0; transform: translateX(var(--offset)); animation: moveBox 1s infinite alternate; } @keyframes moveBox { 0% { --offset: 0; } 50% { --offset: 50px; } 100% { --offset: 100px; } }
Анимация не будет работать гладко. Прямоугольник анимируется только на значениях (0, 50px, 100px). Согласно спецификации CSS:
Любое пользовательское свойство в правиле @keyframes анимируется. Это влияет на то, как оно обрабатывается при обращении к нему через функцию var() в свойстве анимации. Когда хочется, чтобы вышеприведенная анимация работала, мы должны анимировать по-старому. То есть нужно заменить переменную фактическим свойством CSS.
@keyframes moveBox { 0% { transform: translateX(0); } 50% { transform: translateX(50px); } 100% { transform: translateX(100px); } }
Обновление: 9 октября 2020 года
Данни Винтер указал, что можно анимировать CSS-переменные внутри ключевых кадров, регистрируя их с помощью @property. Сейчас это поддерживается в браузерах Chromium.
@property --offset { syntax: "<length-percentage>"; inherits: true; initial-value: 0px; }
Расчеты
Возможно, вы не знаете, что с переменными CSS можно выполнять вычисления. Рассмотрим следующий пример, который я объяснял ранее.
.c-avatar { display: inline-block; width: calc(var(--size, 1) * 30px); height: calc(var(--size, 1) * 30px); }
У нас могут быть вариации аватара. Я установил значение по умолчанию в 1, поэтому размер по умолчанию равен (30px * 30px). Обратите внимание на различные вариации классов и на то, как изменение значения --size приводит к изменению размера аватара.
.c-avatar--small { --size: 2; } .c-avatar--medium { --size: 3; } .c-avatar--large { --size: 4; }
В DevTools есть несколько полезных трюков, чтобы облегчить нам работу с переменными CSS. Давайте исследуем их!
Возможность увидеть значение цвета
Разве не полезно видеть визуальный индикатор для значения цвета или фона, когда вы используете переменную CSS? Chrome и Edge показывают цвет.

Вычисленные значения
Чтобы увидеть вычисленное значение, наведите указатель мыши или кликните — в зависимости от браузера.

Все вычисленные значения отображаются при наведении курсора. За исключением Safari, где для этого нужно нажать кнопку с двумя линиями.
Автозавершение переменных CSS
В большом проекте трудно запомнить все имена переменных. Но можно ввести --, какие-то символы и получить список с переменными CSS на странице. Это работает в Chrome, Firefox и Edge.
Отключение переменной
Когда вам нужно отключить переменную CSS от всех использующих ее элементов, это можно сделать, сняв флажок с элемента, для которого она определена. Смотрите рисунок ниже:

Заключение
Я счастлив, что у меня наконец-то есть для них отдельная страница. Я надеюсь, что вы нашли это полезным, и если да, пожалуйста, поделитесь информацией. Спасибо за чтение!
Я пишу электронную книгу
Рад сообщить вам, что пишу электронную книгу об отладке CSS.

Если вам интересно, перейдите на debuggingcss.com и подпишитесь на обновления о книге.

- Курс «Python для веб-разработки»
- Профессия Веб-разработчик
- Профессия Java-разработчик с нуля
- Курс по JavaScript
- Профессия iOS-разработчик с нуля
- Профессия Android-разработчик с нуля
- Обучение профессии Data Science с нуля
- Онлайн-буткемп по Data Science
- Обучение профессии Data Analyst с нуля
- Онлайн-буткемп по Data Analytics
- Курс по Machine Learning
- Курс «Математика и Machine Learning для Data Science»
- Продвинутый курс «Machine Learning Pro + Deep Learning»
- Курс по аналитике данных
- Курс по DevOps
- Профессия UX-дизайнер с нуля
- Профессия Web-дизайнер
Читать еще
ссылка на оригинал статьи https://habr.com/ru/company/skillfactory/blog/523130/
Добавить комментарий