Css переменные константы. CSS переменные — практические советы по работе




Кто уже давно занимается вёрсткой, много раз чувствовали, что CSS-код труден для правок. Например, Вам захотелось поменять цветовую гамму на всей странице. Что для этого нужно? Поменять у всех блоков один цвет на другой. Неудобно? Согласен, для этого придумали SASS и LESS , однако, это так себе выход. Например, Вам хочется заменить всю цветовую гамму через JavaScript , или увеличить ширину нескольких блоков в 2 раза? Очевидно, что работа эта требует написание однообразного кода. К счастью, относительно недавно появилась возможность задавать переменные прямо в CSS , и браузеры их без проблем обрабатывают. Об этом мы поговорим в этой статье.

Давайте разберём следующий код:







Заголовок

Некоторый текст...


Подвал


Объявляются в псевдоэлементе root (хотя можно и прямо в самих элементах объявлять переменные). Использование же их очень простое: вместо конкретного значения свойства пишется var(имя_переменной) . Особенно интересно использование переменных вместе с функцией calc() . Благодаря этому можно увеличивать или уменьшать множество элементов на сайте, сохраняя при этом все пропорции.

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

Первичные пользовательские свойства

Это свойство, которое вы можете изменять в разных селекторах, в медиа-запросах или с помощью псевдо-селекторов:hover или:focus или, например, с помощью JavaScript. Обычно она содержит одно значение:

: root { --wrapper: 900px; --guter: 10px; }

Вторичные пользовательские свойства

Это аргументы, которые вычисляются из других. Например, в коде ниже размер ячейки сетки(grid) --rowHeight — вычисляется из нескольких первичных. Результат вычисления применяется к свойству, но никогда не обновляется вручную — только пересчитывается в результате изменения первичных CSS переменных.

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

:root { --wrapper: 900px; --guter: 10px; / * s-префикс обозначает вторичное пользовательское свойство * / --s-rh:calc((var(--wrapper)-(3*var(--guter)))/4); }

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

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

Во моих примерах я объявляю CSS переменные в:root , который представляет собой элемент :

:root { ---bgColor: red; }

Однако, в этом нет строгой необходимости, и более того, это не очень хорошая практика .

Большинство причин, по которым не рекомендуется задавать CSS переменные в глобальной области видимости в Javascript также применимы к CSS. Если бы вы при этом захотели использовать пользовательское свойство для фона-цвета -bgColor в разных компонентах, то столкнулись бы со всеми проблемами, связанными с областью видимости. Лучше всего объявлять их в селекторе, например, если вы работаете в компонентах:

My-component { ---bgColor: red; } .some-other-component { ---bgColor: blue; }

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

Установка величин по умолчанию

С помощью CSS переменных вы можете установить величину(или несколько величин) по умолчанию. Это означает, что в некоторых ситуациях вам нужно только объявить свои переменные в той точке, в которой они должны измениться. В коде ниже CSS переменная -bgColor для поля объявляется только при достижении ширины в 40em — до этого она принимает значение по умолчанию(red):

В этом втором примере вы можете видеть, что селекторы h1 и p имеют разные величины по умолчанию для своего свойства цвета, но оба принимают переменную при наведении:

Использование пользовательских свойств с препроцессорными

Один из недостатков CSS-аргументов — они не работают в медиа-запросах или псевдоклассах, например:nth-child(var(-n)) не будет работать. Поэтому, скорее всего, вы все равно захотите использовать препроцессорные аргументы .

Я бы предостерег от смешивания этих двух типов пользовательских свойств, если вы не полностью понимаете их отличия. Аргументы Sass скомпилируются до того, как ваш код попадает в браузер, тогда как в CSS они не получат вычисленное значение, пока не попадут в браузер. Это означает, что в приведенном ниже коде величина ширины для.box1 будет работать, но.box2 выдает ошибку, потому что величина для -halfWidth передается браузеру в виде строки:

$width: 600px; $halfWidth: $width/2; :root { --halfWidth: $width/2; } .box1 { ширина: $halfWidth; } .box2 { width: var(--halfWidth); // это некорректно }

Однако вы можете использовать calc() , как в предыдущих примерах. Смотрите результат в ниже:

Если вы проинспектируете элемент в консоли Chrome и перейдете на вкладку «Вычисляемые стили»(Computed Styles), вы увидите, что значение ширины для.box2 не вычисляется. В нашей компании мы используем много функций Sass, например, для вычисления rem из пикселей при определении размера. Я обнаружил, что это оказалось проблемой, когда я попытался передать функцию Sass в аргумент CSS, например, --width: rem (600px) . Есть плагин PostCSS , который может преобразовывать пиксели в rem чтобы достичь желаемого результата, но мне нужно будет немного поэкспериментировать с ними, прежде чем я буду уверенно рекомендовать их использовать с CSS переменными.

Тем не менее, существуют сценарии, в которых использование препроцессорных и CSS переменных в одном блоке кода вместе имеет смысл, например, в медиа-запросах, как упоминалось ранее.

Всем привет, тема переменных в CSS давно ходит по интернету, однако не все знают о том, что это такое, да и сама технология не так давно вышла в релиз. И хоть использовать её во многих случаях рановато, уже пора понимать что она из себя представляет и как ею пользоваться. Давайте попробуем разобраться с технологией вместе. Обращу ваше внимание, что эта статья для тех, кто не знает о CSS переменных (кастомных свойствах) или только слышал о них. Если вы знакомы и умеете работать с данной фичей, то вам данная статья будет не интересна.

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

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

:root { --body-background: #ccc; } body { background-color: var(--body-background); }
Как видно из листинга выше, переменные объявляются двумя дефисами перед именем:
--variable-name

Чтобы использовать переменную, необходимо воспользоваться функцией var . Она имеет 2 параметра. Это, естественно, имя переменной, а вторым необязательным параметром идёт значение свойства, которое необходимо использовать в случае отсутствия переменной.

На этом набор новых возможностей с приходом переменных, разумеется, не заканчивается. Имея переменные в арсенале CSS, мы получаем большую гибкость в написании стилей. Например, теперь чтобы составить медиазапрос для экранов <320px в ширину, не нужно переопределять свойство целиком. Достаточно изменить значение переменной. Т.е.

Title { --wrapper-width: 50%; width: var(--wrapper-width); } @media (max-width: 320px) { --wrapper-width: 100%; }
Всё! Этого достаточно, чтобы свойство width изменило свое значение!

Если CSS способен отслеживать изменения своих переменных, это значит, что с этим можно взаимодействовать различными способами.

Что насчёт JavaScript?

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

Title { --background: blue; background-color: var(--background); }
changeColor() { this.setState({ style: {"--background": "green"} }); }

Title

Теперь по клику на элемент с классом title будет меняться цвет фона у элемента. Круто? Ещё бы! Не нужно добавлять новый класс, переопределять свойство или делать другие действия, способствующие изменению фонового цвета у элемента.

Ремарка

Если кто-то не знаком с React или кому-то просто непонятно, что произошло. Мы просто средствами JavaScript изменили аттрибут style у элемента, изменив значение переменной
--background


Используя переменные, изменять css извне стало проще, методов использования можно придумать массу, а мы пойдем дальше.

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

Нужно сказать пару слов об области видимости CSS переменных, здесь всё просто. Объявленная переменная доступна всем селекторам дочерних элементов данного селектора. Т.е. в листинге ниже использовать переменную --b в тэге html будет нельзя. А вот переменная --a в body и всех дочерних элементах будет работать без проблем (если её конечно не переопределят где-то ниже).

Html { --a: #ccc; } body { --b: #a3a3a3; }
(я знаю, что цвета в примерах скучные, но я плохо помню цвета по hex-коду:))

Переменные и calc

Как и любое числовое значение свойства, вы можете использовать переменную в функции calc .

Title { --title-width: 300px; width: calc(var(--title-width) + 150px); }
Круто! Особенно если учесть что переменную --title-width , можно менять как внутри CSS, так и извне.

Заметьте, что величину мы обязаны положить в переменную. Дописать px , % , rem и т.д. к вызванной переменной у нас не получится. Однако ничто не мешает нам умножить с помощью функции calc значение на единицу в необходимой нам величине.

Title { --title-width: 300; /* так не сработает */ width: var(--title-width)px; /* так сработает */ width: calc(var(--title-width) * 1px); }

В заключение

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

Последнее обновление: 18.11.2018

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

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

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

Variables в CSS3

Первый блок.
Второй блок.

Третий блок.

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

Text-color: #ff4757; --text-size: 20px;

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

#p1 { color: var(--text-color); font-size: var(--text-size); }

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

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

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

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

Первый блок.
Второй блок.

Третий блок.

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

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

:root{ --text-color: #ff4757; --text-size: 20px; }

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

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

Variables в CSS3

Первый блок.
Второй блок.
Третий блок.

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

Color: var(--text-color, var(--reserved-color));

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

Color: var(--text-color, var(--reserved-color, red));

Custom properties (sometimes referred to as CSS variables or cascading variables ) are entities defined by CSS authors that contain specific values to be reused throughout a document. They are set using custom property notation (e.g., --main-color: black; ) and are accessed using the var() function (e.g., color: var(--main-color) ;).

Complex websites have very large amounts of CSS, often with a lot of repeated values. For example, the same color might be used in hundreds of different places, requiring global search and replace if that color needs to change. Custom properties allow a value to be stored in one place, then referenced in multiple other places. An additional benefit is semantic identifiers. For example, --main-text-color is easier to understand than #00ff00 , especially if this same color is also used in other contexts.

Custom properties are subject to the cascade and inherit their value from their parent.

Basic usage

Declaring a custom property:

Element { --main-bg-color: brown; }

Using the custom property:

Element { background-color: var(--main-bg-color); }

First steps with custom properties

Let"s start with this simple CSS that applies the same color to elements of different classes:

One { color: white; background-color: brown; margin: 10px; width: 50px; height: 50px; display: inline-block; } .two { color: white; background-color: black; margin: 10px; width: 150px; height: 70px; display: inline-block; } .three { color: white; background-color: brown; margin: 10px; width: 75px; } .four { color: white; background-color: brown; margin: 10px; width: 100px; } .five { background-color: brown; }

We"ll apply it to this HTML:

1:
2: Text 5 - more text

Which leads us to this:

Notice the repetition in the CSS. The background color is set to brown in several places. For some CSS declarations, it is possible to declare this higher in the cascade and let CSS inheritance solve this problem naturally. For non-trivial projects, this is not always possible. By declaring a custom property on the element and is identical to the selector html, except that its specificity is higher."> :root pseudo-class and using it where needed throughout the document, a CSS author can reduce the need for repetition:

:root { --main-bg-color: brown; } .one { color: white; background-color: var(--main-bg-color); margin: 10px; width: 50px; height: 50px; display: inline-block; } .two { color: white; background-color: black; margin: 10px; width: 150px; height: 70px; display: inline-block; } .three { color: white; background-color: var(--main-bg-color); margin: 10px; width: 75px; } .four { color: white; background-color: var(--main-bg-color); margin: 10px; width: 100px; } .five { background-color: var(--main-bg-color); }

Text - more text

This leads to the same result as the previous example, yet allows for one canonical declaration of the desired property value.

Inheritance of custom properties

Custom properties do inherit. This means that if no value is set for a custom property on a given element, the value of its parent is used. Take this HTML:

With the following CSS:

Two { --test: 10px; } .three { --test: 2em; }

In this case, the results of var(--test) are:

  • For the class="two" element: 10px
  • For the class="three" element: 2em
  • For the class="four" element: 10px (inherited from its parent)
  • For the class="one" element: invalid value , which is the default value of any custom property

Keep in mind that these are custom properties, not actual variables like you might find in other programming languages. The value is computed where it is needed, not stored for use in other rules. For instance, you cannot set a property for an element and expect to retrieve it in a sibling"s descendant"s rule. The property is only set for the matching selector and its descendants, like any normal CSS.

Custom property fallback values

Fallback values aren"t used to fix the browser compatibility. If the browser doesn"t support CSS custom Properties, the fallback value won"t help. It"s just a backup for the browser which supports CSS Custom Properties to choose a different value if the given variable isn"t defined or has an invalid value.

The first argument to the function is the name of the custom property to be substituted. The second argument to the function, if provided, is a fallback value, which is used as the substitution value when the referenced custom property is invalid. The function only accepts two parameters, assigning everything following the first comma as the second parameter. If that second parameter is invalid, such as if a comma-separated list is provided, the fallback will fail. For example:

Two { color: var(--my-var, red); /* Red if --my-var is not defined */ } .three { background-color: var(--my-var, var(--my-background, pink)); /* pink if my-var and --my-background are not defined */ } .three { background-color: var(--my-var, --my-background, pink); /* Invalid: "--my-background, pink" */ }

Including a custom property as a fallback, as seen in the second example above, is the correct way to provide more than one fallback. The technique has been seen to cause performance issues as it takes more time to parse through the variables.

Note : The syntax of the fallback, like that of custom properties , allows commas. For example, var(--foo, red, blue) defines a fallback of red, blue - anything between the first comma and the end of the function is considered a fallback value.

Validity and values

The classical CSS concept of validity, tied to each property, is not very useful in regard to custom properties. When the values of the custom properties are parsed, the browser doesn"t know where they will be used, so must, therefore, consider nearly all values as valid .

Unfortunately, these valid values can be used, via the var() functional notation, in a context where they might not make sense. Properties and custom variables can lead to invalid CSS statements, leading to the new concept of valid at computed time.

What happens with invalid variables?

When the browser encounters an invalid var() substitution, the initial or inherited value of the property is used.

Consider the code snippet below.

HTML

This paragraph is initial black.

CSS

:root { --text-color: 16px; } p { color: blue; } p { color: var(--text-color); }

As expected, the browser substitutes the value of --text-color in place of var(--text-color) , but 16px is not a valid property value for color . After substitution, the property doesn’t make any sense. The browser handles this situation in two steps:

  1. Check if the property color is inheritable. Yes, but

    Doesn"t have any parent with color property. So move on to the next step.

  2. Set the value to its default initial value , i.e., black.

Result

The paragraph color will not be blue because invalid substitution is replaced by the initial value, not by the fallback. If you had written color: 16px without any variable substitutes, then it was a syntax error. The previous declaration will then be used.

Note : While a syntax error in a CSS property / value pair will lead to the line being ignored, using a cascaded value, invalid substitution -- using a custom property value that is invalid -- is not ignored, leading to the value to be inherited.

Values in JavaScript

To use the values of custom properties in JavaScript, it is just like standard properties.

// get variable from inline style element.style.getPropertyValue("--my-var"); // get variable from wherever getComputedStyle(element).getPropertyValue("--my-var"); // set variable on inline style element.style.setProperty("--my-var", jsVar + 4);