Как сделать переменную css

Добавил пользователь Евгений Кузнецов
Обновлено: 28.09.2024

CSS-переменные всё больше используются при вёрстке, поскольку это довольно удобный инструмент, упрощающий работу. Если не оглядываться на IE11, то css-переменные хорошо поддерживаются браузерами. Во всяком случае все современные версии без проблем.

Ответ кроется в понимании того, для кого именно создаются css-переменные и какое у них будет назначение.

CSS vs Sass

Тут всё просто. Если вы пишите на Sass какой-то конкретный дизайн, то скорее всего css-переменные будут не нужны. Sass-переменные с лихвой покроют все потребности вёрстки. Если что-то изменилось, то меняем scss-файл, компилируем и всё прекрасно работает.

Так мы делаем уже много лет, и здесь ничего не меняется.

CSS only

Предположим вы сделали html/css-компонент, который состоит из нескольких классов и имеет какое-то определённое оформление. Например в красных оттенках. Чтобы использовать этот же модуль в другом дизайне, например в синем, потребуется его переписывать. Логично было бы вынести эти изменяемые свойства в переменные.

То есть подход к CSS-переменным должен быть точно таким же как и в других языках программирования. И он состоит их двух вещей:

  • нужно объявить переменную
  • можно её использовать

Объявление css-переменных

Мы объявляем переменную --mybg в блоке .my1 . Поскольку первый .my2 вложен в .my1 , то фон будет синим. А второй .my2 не вложен, поэтому для него не будет фона, поскольку переменная --mybg там не определена.

Этот пример позволяет понять первый подход к определению css-переменных — выносить переменные на более высокий уровень иерархии html-документа. Обычно это тэг BODY (поскольку все остальные уже вложенные в него), либо специальный псевдоэлемент :root .

Если мы объявим переменную так:

то все .my2 окажутся с синим фоном.

Такой подход порождает проблемы, с которой ведут борьбу программисты всех языков: замусоривание глобальной области видимости и сложность с именованием переменных.

Скажем у нас будет несколько блоков, где нужно поменять цвет фона. Это приводит к тому, что необходимо заботится о правильном именовании переменных.

Это, конечно, создаёт определённую путаницу и усложняет код. Но, если проект небольшой, то такой подход, когда root-переменные объявляются отдельно, может служит примером замены аналогичного Sass-проекта.

То есть когда вы пишите самостоятельный html/css-компонент, есть смысл вынести его настройки в css-переменные, чтобы менять только их.

Другой подход к объявлению переменных — противоположный: переменная объявляется в пределах блока, который её будет использовать. Для сложных html-компонентов это может быть контейнер, а для простых — для указанного css-класса.

Очень часто встречается такой вариант:

На самом деле он бессмыслен, поскольку в одном блоке и задаётся переменная и тут же используется. Единственным способом изменить цвет фона блока будет использование style :

В некоторых случаях блок .my разбивают на две части: переменная объявляется где-то вверху кода, а основные стили уже внизу файла. Но такой вариант элементарно неудобный, поэтому лучше всего использовать возможность указывать дефолтное значение для необъявленной переменной.

Если --bg не существует, то будет использовано значение по умолчанию ( red ).

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

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

От того, где именно будет объявлена переменная зависит очень многое. Частая практика объявления в :root создаёт проблему конфликта имён переменных.

Например у нас есть два блока:

Мы видим, что в обоих блоках используется переменная --color , что вполне логично для пределов своего блока. Но если мы объявим эту переменную выше в :root , то она окажется одной и той же сразу для двух блоков.

Чтобы избегать таких конфликтов, переменные следует изменять в пределах своего блока:

Если css-переменная используется только в каком-то классе или html-тэге, то не нужно выносить её определение на более высокий уровень.

Стилизация через дополнительный класс

Пусть у нас объявлен класс:

После этого достаточно лишь указать второй класс, чтобы получить новую стилизацию.

Данный приём позволяет создавать новые классы на основе существующих, используя только их css-переменные. Это позволяет стилизовать любые классы через дополнительные.

CSS и Sass

При использовании Sass появляется еще больше возможностей так как объединяются две технологии. Общий принцип можно свести к одному примеру:

Там где нужно изменить цвет через Sass, меняется sass-переменная, а если нужно изменить через CSS, то используется css-переменная.

Область применения css-переменных

Конечно достоинства css-переменных проявляются в тех проектах, которые предполагают некоторую смену дизайна. Например слайдер, где нужно поменять цвет dot-элементов навигации. Если они вынесены css-переменными, то сделать это проще, чем менять css или sass-код.


Но у такого элемента очень большая вариативность: можно ещё менять ширину бордюра и его стиль, а также разные скругления. Если делать для этого отдельные классы, то это существенно раздует css-файл, при том, что элемент не самый востребованный.

С помощью css-переменных проблема решается элементарно:


Ещё одно применение css-переменных: задание базовых значений типографики. Опять же, пример из Berry 3:

При использовании готового css-файла из дистрибутива фреймворка, чтобы изменить общий шрифт или фон, потребовалось бы переопределить их в отдельном css-файле. Через css-переменные это делается более элегантно:

Функция var() используется для вставки значения CSS переменной.

CSS переменные имеют доступ к DOM, что означает, что вы можете создавать переменные с локальной или глобальной областью видимости, изменять переменные с помощью JavaScript и изменять переменные на основе медиа-запросов.

Хороший способ использовать переменные CSS - это когда дело доходит до цветов вашего дизайна. Вместо того, чтобы копировать и вставлять одни и те же цвета снова и снова, вы можете поместить их в переменные.

Традиционный путь

В следующем примере показан традиционный способ определения некоторых цветов в таблице стилей (путем определения используемых цветов для каждого конкретного элемента):

Пример

Синтаксис функции var()

Функция var() используется для вставки значения CSS переменной.

Синтаксис функции var() следующий:

Значение Описание
имя Обязательно. Имя переменной (должно начинаться с двух тире)
значение Не обязательно. Резервное значение (используется, если переменная не найдена)

Примечание: Имя переменной должно начинаться с двух дефисов (-), и оно чувствительно к регистру!

Как работает var()

Прежде всего: переменные CSS могут иметь глобальную или локальную область видимости.

Доступ к глобальным переменным можно получить / использовать во всем документе, в то время как локальные переменные можно использовать только внутри селектора, в котором он объявлен.

Чтобы создать переменную с глобальной областью видимости, объявите её внутри селектора :root . Селектор :root соответствует корневому элементу документа.

Чтобы создать переменную с локальной областью видимости, объявите её внутри селектора, который будет её использовать.

Следующий пример аналогичен приведённому выше, но здесь мы используем функцию var() .

Сначала мы объявляем две глобальные переменные (--blue и --white). Затем используем функцию var() , чтобы вставить значение переменных позже в таблицу стилей:

Пример

.container color: var(--blue);
background-color: var(--white);
padding: 15px;
>

button background-color: var(--white);
color: var(--blue);
border: 1px solid var(--blue);
padding: 5px;
>

Преимущества использования var() :

  • упрощает чтение кода (более понятный)
  • значительно упрощает изменение значений цвета

Чтобы изменить сине-белый цвет на более мягкий синий и белый, вам просто нужно изменить значения двух переменных:

Пример

.container color: var(--blue);
background-color: var(--white);
padding: 15px;
>

button background-color: var(--white);
color: var(--blue);
border: 1px solid var(--blue);
padding: 5px;
>

Поддержка браузерами

Числа в таблице указывают первую версию браузера, которая полностью поддерживает функцию var() .

Как и в языках программирования, в CSS можно определять переменные. Переменные в CSS могут хранить стандартные значения, которые можно присвоить, обычным свойствам CSS, например, цвет фона, цвет шрифта, высоту шрифта, ширину и высоту элементов и так далее. Затем их можно многократно использовать в различных частях определения стилей.

Стоит отметить, что хотя часто используется термин "переменные" (css variables), официально они называются custom properties (кастомные или настраиваемые свойства).

Определение переменных CSS должно начинаться с префикса -- , например, --my-color . Они могут быть определены для любого элемента. Например:

Здесь в коде CSS для элемента div определены две переменныx: --text-color и --text-size

С помощью выражения var() мы можем ссылаться на эти переменные в любой части кода CSS:

В итоге первый блок получит высоту шрифта из --text-size, второй блок получит цвет шрифта из --text-color, а третий блок получит оба этих компонента.

Custom properties and variables in CSS

Если нам потребуется изменить цвет текста, достаточно будет изменить значение переменной.

Подобные переменные можно определить для любого элемента. При этом они наследуется дочерними элементами. Так, в примере выше мы видим, что вложенный элемент параграфа получает стили от родительского div.

Но если бы параграф находился бы вне блока div:

Тогда бы значения из переменных к нему бы не применялись:

Переменные в CSS

Если же необходимо, чтобы переменные могли бы использоваться глобально для всех элементов, тогда их определяют для элемента :root

Резервные значения

При определения переменных могут содержать какие-нибудь ошибки, например, переменная не определена (вообще не определена или в ее названии опечатка). В этом случае мы можем указать при применении переменной резервные значения, которые бдут применяться в случае, если значение переменной некорректно.

Второй параметр в функции var() позволяет задать резервное значение. Это может быть как точное значение, так и опять же значение другой переменной:

Для второй переменной можно также определить резервное значение, если она некорректна:

CSS-переменные — это настраиваемые свойства, которые обычно каскадируются и даже наследуются. Они начинаются с зарезервированного префикса -- , и относительно их значения нет никаких правил или ограничений, подойдёт любое, даже простой пробел. Обработка ошибок в их значениях не происходит до той поры, пока они не будут использованы. На их значения следует ссылаться через функцию var(--name) , которую можно использовать в любом CSS-свойстве. На случай, когда переменная не установлена, функция var() поддерживает второй аргумент в качестве резерва.

Поддержка CSS-переменных браузерами

CSS-переменные поддерживаются в браузерах более 95% пользователей. В браузере, который не поддерживает CSS-переменные, не будет работать и функция var() . Случай уже редкий, но как и прежде, для каждой новой CSS-функции, можно использовать каскадность CSS. Вот пример:

В зависимости от реализации CSS-переменных в браузере и значения --accent-color может быть четыре варианта развития событий:

  1. Если браузер не поддерживает CSS-переменные, он будет игнорировать для background вторую строку и применит красный цвет для фона.
  2. Если браузер поддерживает CSS-переменные, значение в --accent-color соответствует цвету, это значение будет применено для фона.
  3. Если браузер поддерживает CSS-переменные, но --accent-color не установлен, будет использоваться оранжевый — это запасной вариант из второго аргумента var() .
  4. Если браузер поддерживает CSS-переменные, а --accent-color будет содержать бессмысленное значение для свойства (например, 42deg вместо ожидаемого цвета), фон окажется прозрачным.

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

В таком случае должен примениться красный цвет, т.к. браузер проигнорирует вторую строку вместе со всем, что ему будет не понятно. В примере кода, где 42deg указано в значении свойства без использования переменных, браузер избавится от неправильного свойства во время синтаксического анализа.
В случае с переменной, браузер узнает, действительно ли ее объявление, гораздо позже. К этому времени он уже отбросит остальные каскадные значения (т.к. он должен содержать только одно вычисленное значение) и, не сумев разобрать пару свойство-значение, вернётся к исходному значению — в данном случае прозрачному.

Когда резервные значения не помогают

Резервные значения для старых браузеров подходят в простых случаях, однако запросы CSS-функций — правило @supports — могут им предоставлять совершенно другой CSS. Для примера, можно установить красный фон в браузерах, которые не поддерживают CSS-переменные и зеленый фон тем, которые их поддерживают:

Различия CSS-переменных и переменных препроцессора

CSS-препроцессоры — это программы, которые выполняются один раз, для генерации статического CSS-кода. В них переменные ведут себя, как переменные императивного языка программирования, с лексической областью видимости и множеством значений в процессе выполнения. Их можно использовать в любом месте таблицы стилей: селекторах, условных выражениях, свойствах, значениях и т.д., даже для генерации только фрагмента значения или селектора.

CSS-переменные можно использовать только в значениях и только для целых токенов. Они реактивны и остаются активными на протяжении всего времени существования страницы. Они используют динамическую область видимости для каждого элемента и не могут быть частью императивных вычислений, поскольку имеют только одно значение для каждого состояния. Когда CSS-переменные устанавливаются извне (например, через HTML или JavaScript), следует использовать их для чистых данных, а не для CSS-значений, таких как длина или проценты.

Динамическая вместо лексической области видимости

Область видимости переменных в препроцессорах сводится к вложенным блокам фигурных скобок. Однако, поскольку CSS-переменные являются свойствами, их область видимости (в отличие от переменных препроцессора) основана на модели DOM. Это означает, что CSS-переменные разрешаются для каждого элемента, а не для каждой области, и они наследуются как обычные свойства. Рассмотрим следующий пример CSS-переменных:

При наведении курсора серая тень кнопки становится небесно-голубой. Попробуем преобразовать это в язык препроцессора Sass:

CSS-переменные реактивны

Наиболее важным отличием от переменных препроцессора является то, что CSS-переменные являются реактивными. Они остаются активными на протяжении всего времени жизни страницы, и их обновление обновляет все отношения, которые ссылаются на них. В этом смысле они больше похожи на свойства в реактивных фреймворках, таких как Angular, Mavo и Vue, чем на переменные в традиционных языках программирования или препроцессорных языках. Поскольку они являются свойствами, их можно обновлять с помощью любого механизма, который обновляет свойства CSS: таблицы стилей, встроенные стили и даже JavaScript.

Циклы делают переменные CSS недействительными во время вычисления значения

Рассмотрим следующий фрагмент Sass:

Результат будет примерно таким:

CSS-переменные — это совсем другая история, естественное следствие их реактивности. Посмотрим на тот же фрагмент, но с CSS-переменными:

Переменная, зависящая от самой себя, создала бы бесконечный цикл, которого не должно быть в декларативном языке, таком как CSS. Чтобы избежать этого, циклы делают все задействованные переменные недействительными во время вычисления значения. Сюда входят циклы длины 1 (в примере выше) и более длинные циклические цепочки, где переменная A зависит от B, которая зависит от C, и так далее до Z, которая зависит от A. Все 26 (A..Z) были бы недействительными во время вычисления значения, что сделало бы их значение равным начальному, и это по существу дало бы такой же результат, как если бы они никогда не были установлены.

CSS-переменные облегчают разделение поведения и стиля

Реактивность переменных CSS — это делает их мощными. При правильном использовании стили могут оставаться в CSS, а вычисления — в JavaScript, где им и положено находиться. Предположим, нужен радиальный градиентный фон, на котором центральная точка градиента следует за курсором мыши. Раньше приходилось генерировать весь градиент в JavaScript и устанавливать его во встроенном (inline) стиле HTML-элемента при каждом движении мыши. С CSS-переменными в JavaScript необходимо установить только две переменные: --mouse-x и --mouse-y . В обычном JavaScript это может выглядеть так:

Затем надо в CSS настроить эффект, например, так:

Совершенно другой эффект будет со слоистыми градиентами, в которых используется одна и та же центральная точка:

Предположим, надо сделать, чтобы оттенки и угол в коническом градиенте менялись в зависимости от времени суток. Тот же самый JavaScript будет работать и для мыши, поэтому следует добавить немного JavaScript, который устанавливает CSS-переменную с текущим часом (0–23):

Затем включить эту переменную в CSS и использовать её в вычислениях:

Поскольку все три переменные, установленные с помощью JavaScript, являются чистыми данными, а не значениями из CSS, их можно использовать в нескольких несвязанных CSS-правилах. (Они не относятся непосредственно к эффектам только для фона.)

CSS-переменные упрощают инкапсуляцию стилей

CSS-переменные позволяют повторно использовать и настраивать CSS-код, поскольку они делают возможной инкапсуляцию. Предположим, есть стиль плоской кнопки, примененный к классу .flat . Его упрощенный CSS-код выглядит так:

Допустим, ещё нужны кнопки разного цвета для разных действий, например красная кнопка для опасного действия. Можно добавить поддержку класса-модификатора .danger и переопределять соответствующие объявления:

Заменим цвет переменной, чтобы избежать дублирования:

Теперь всё упростилось до переопределения одного свойства: --color :

Это триумф краткости, но гораздо больший триумф инкапсуляции — роскошь, которую CSS не всегда позволял своим разработчикам. Фактически, натягивание тем на сторонний CSS-код раньше означало близкое знакомство с его внутренней структурой, а изменение стороннего кода требовало аналогичных обширных изменений и в коде тем. Теперь настраиваемые CSS-свойства могут служить своего рода API: кардинально меняя базовый стиль только с помощью настраиваемых свойств.

Возвращаясь к примеру с кнопкой, предположим, что надо добавить переход для более плавного эффекта наведения. Ещё надо, чтобы новый цвет фона увеличивался внутрь от границы вместо затухания по умолчанию, которое получается при переходе между двумя цветами фона. Для этого нужно имитировать фон с помощью box-shadow :

Несмотря на то, что сама реализация довольно существенно изменилась, работают все цветовые темы кнопок. Если бы было нужно переопределять CSS для создания тем, код этих тем был бы сломан.

Эта возможность — не экономия нескольких символов или времени на обслуживание, она является истинной ценностью настраиваемых свойств. Они позволяют делиться кодом, который может быть повторно использован и настроен другими разработчиками, при этом допускает полностью изменять его внутреннюю структуру. Пользовательские свойства также являются единственным способом создания компонентов shadow DOM, потому что, в отличие от любых других CSS-свойств, они выходят за пределы shadow DOM.

Создание цветовых палитр

Как правило, руководства по стилю начинаются с одного или нескольких основных акцентных цветов, из которых создается остальная палитра. Использование переменных только для основных цветов будет более эффективно, чем необходимость вручную настраивать каждый вариант цвета. К сожалению, в CSS пока нет функций изменения цвета. Между тем, вместо того, чтобы определить базовый цвет как одну переменную, нужно использовать отдельные переменные для компонентов цвета.

Из цветовых синтаксисов, доступных для CSS в настоящее время, hsl() имеет тенденцию работать лучше для создания цветовых вариаций (до тех пор, пока не получим lch() , который будет намного круче из-за своего более широкого диапазона и восприятия). Если понадобятся только варианты светлее/темнее и прозрачнее, можно использовать переменную как для оттенка, так и для насыщенности:

Эти переменные можно использовать в CSS или создавать на лету новые варианты. Да, есть ещё небольшое дублирование — яркость основного цвета — но если планируется создать много альфа-вариаций, можно добавить переменную со всеми тремя координатами или одну с яркостью.

Предотвращение наследования

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

Это приводит к тому, что тонкое свечение применяется не только к элементу

, но и к любому из его дочерних элементов, включая ссылки , выделение и т.д.

Читайте также: