Как использовать переменные в CSS

Как использовать переменные в CSS

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

К примеру, через CSS свойство можно задать цвет бренда (—primarycolor: #7232FA) и использовать это значение в любых компонентах или стилях, где упоминается цвет бренда (background: var(—primarycolor);)

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

Как определить CSS переменную

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

--primarycolor: #0ad0f9ff; /* RGB alpha hexadecimal color notation */

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

Имена кастомных свойств регистрозависимые. То есть —primaryColor и –primarycolor это разные переменные. Это отхождение от стандартного поведения CSS, где свойства и значения не чувствительны к регистру. Правила именования совпадают с ECMAScript.

Как и другие свойства, например display или font, кастомные свойства необходимо определять внутри блока. Очень часто кастомные свойства определяют в псевдоэлементе :root:

:root { --primarycolor: #0ad0f9ff; }

:root – псевдоэлемент, отсылающий к корневому элементу документа. Для HTML корнем будет выступать тег html. Для svg документов корнем будет <svg>. :root делает свойства доступные во всем документе сразу.

Использование CSS переменных

Чтобы использовать кастомное свойство как переменную, нужно воспользоваться функцией var(). Например, чтобы задать background color значение переменной –primarycolor, можно написать следующим образом:

body { background-color: var(--primarycolor); }

Значение нашего кастомного свойства станет вычисленным значением свойства background-color. Сейчас с помощью CSS переменных можно задавать значения только в стандартных CSS свойствах. Нельзя в переменной хранить название свойства и потом его вызвать. Код ниже работать не будет:

:root { --top-border: border-top; /* Can't set a property as custom property's value */ var(--top-border): 10px solid #bc84d8; /* Can't use a variable as a property */ }

В переменной также нельзя хранить пару свойство-значение. Код ниже работать также не будет:

:root { --text-color: 'color: orange'; /* Invalid property value */ } body { var(--text-color); /* Invalid use of a property */ }

Также нельзя конкатенировать переменные с частью значения:

:root { --base-font-size: 10; } body { font: var(--base-font-size)px / 1.25 sans-serif; /* Invalid CSS syntax */ }

Кастомные CSS свойства или CSS переменные

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

Мы называем кастомные свойства переменными потому что на данный момент мы не можем использовать их по-другому. Теоретически, это не совсем взаимозаменяемые термины. На практике на данный момент это синонимы. Я чаще пишу в этой статье кастомные свойства, потому что это их правильное название. Когда понятнее написать переменные, я пишу переменные.

Как задать запасное значение

Функция var() принимает 2 аргумента. Первый параметр – само кастомное свойство. Второй параметр необязательный и задает значение. Это значение будет отрабатывать как значение по-умолчанию в ситуациях, когда свойство не определено. Разберем пример ниже:

.btn__call-to-action { background: var(--accent-color, deepskyblue); }

Если значение —accent-color задано, например #f30 – то цвет заливки для любого элемента с классом .btn__call-to-action будет red-orange. Если же значение не задано, то будет deep sky blue.

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

body { background-color: var(--books-bg, var(--arts-bg)); }

По коду выше если если —books-bg определен, то цвет фона будет равен значению —books-bg. Иначе фон будет равен значению —arts-bg. Если и оно не задано, то цвет будет равен начально заданному значению – в нашем случае transparent.

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

:root { --text-primary: #600; --footer-link-hover: #0cg; /* Not a valid color value */ } body { color: var(--text-primary); } a:link { color: blue; } a:hover { color: red; } footer a:hover { color: var(--footer-link-hover); }

В нашем примере значение —footer-link-hover – невалидный цвет. Поэтому footer a:hover унаследует цвет элемента body.

Кастомные свойства работают как обычные. Если значение невалидно или не определено, CSS парсер использует унаследованное значение, если таковое есть (color или font). Или же будет подобрано начальное значение, если нет унаследованного (как с background-color).

Каскадные значения

Кастомные свойства также придерживаются правил каскадирования. Их значения можно переписать правилами ниже по коду:

:root { --text-color: #190736; /* navy */ } body { --text-color: #333; /* dark gray */ } body { color: var(--text-color); }

В примере выше текст body будет темно серый. Также можно сбрасывать значения для каждого селектора. Добавим несколько правил:

:root { --text-color: #190736; /* navy */ } body { --text-color: #333; /* dark gray */ } p { --text-color: #f60; /* orange */ } body { color: var(--text-color); } p { color: var(--text-color) }

В этом примере любой текст внутри <p> будет оранжевый. А текст внутри <div> или любого другого тега будет темно серый. Значение кастомного свойства можно задать через атрибут style — style=»—brand-color: #9a09af».

Кастомные свойства и цветовые палитры

Кастомные свойства отлично подходят для управления HSL цветовыми палитрами. HSL расшифровывается как hue, saturation, lightness или оттенок, насыщенность яркость. Это цветовая модель, в основе которой лежит яркость, она схожа с RGB. HSL значения в CSS можно использовать в функциях hsl() и hsla().

Hsl() функция принимает 3 аргумента – оттенок, насыщенность и яркость. Hsla() принимает четвертый аргумент – прозрачность (от 0 до 1).

RGB представляет цвет как пропорцию красного, зеленого и синего. HSL использует для определения цвета круг, где оттенок определяется градусом на этом круге, а тон или тень задаются через насыщенность и яркость. Насыщенность варьируется от 0% до 100%, где 0% — серый, а 100% — сам цвет. Яркость также варьируется от 0% до 100%, где 0% — это черный, 100% — белый, а 50% — нормальный цвет.

Как использовать переменные в CSS

В системе HSL основные цвета (красный, зеленый и синий) расположены на расстоянии 120 градусов друг от друга. То есть 0/360 градусов, 120 грудусов и 240. Вторичные цвета также расположены на расстоянии по 120 градусов – голубой, пурпурный и желтый – 180 градусов, 300 и 60/420 градусов. Третьи по значимости, четвертые итд цвета идут с шагом примерно в 10 градусов. Синий на HSL будет hsl(240, 100%, 50%).

Единицы измерения HSL аргументов

Если для первого параметра hsl() или hsla() использовать значение без единиц измерения, браузер предположит, что это угол в градусах. Можно также использовать любые единицы измерения углов в CSS. Синий можно записать как hsl(240deg, 100%, 50%), hsl(4.188rad, 100%, 50%) или hsla(0.66turn, 100% 50%).

А уже дальше интересно. Значение оттенка можно задать через кастомное свойство, а светлее или темнее можно сделать через насыщенность и яркость.

:root { --brand-hue: 270deg; /* purple */ --brand-hue-alt: .25turn; /* green */ /* hsl() and hsla() can accept comma-separated or space-separated arguments, but older browsers (such as Internet Explorer 11) only support comma-separated arguments. */ --brand-primary: hsl( var( --brand-hue ) 100% 50% ); --brand-highlight: hsl( var( --brand-hue ) 100% 75% ); --brand-lowlight: hsl( var( --brand-hue ) 100% 25% ); --brand-inactive: hsl( var( --brand-hue ) 50% 50% ); --brand-secondary: hsl( var( --brand-hue-alt ) 100% 50% ); --brand-2nd-highlight: hsl( var( --brand-hue-alt ) 100% 75% ); --brand-2nd-lowlight: hsl( var( --brand-hue-alt ) 100% 25% ); --brand-2nd-inactive: hsl( var( --brand-hue-alt ) 50% 50% ); }

CSS выше создаст палитру как ниже.

Как использовать переменные в CSS

Это простая версия. С помощью кастомных свойств можно настроить насыщенность и яркость.

Надежный способ генерации палитры

Dieter Raber обсуждает технику надежной генерации палитры в статье «Создание цветовых тем с помощью кастомных свойств, HSL и немного calc()».

Второй способ – комбинация кастомных свойств и функции calc() для генерации цветовой схемы из базового. Создадим цветовую схему из квадратов в следующем примере. Квадратная схема цветов состоит из 4 цветов равноудаленных друг от друга на цветовом колесе – т.е. по 90 градусов.

:root { --base-hue: 310deg; /* Hot pink */ --distance: 90deg; --color-a: hsl( var(--base-hue), 100%, 50% ); --color-b: hsl( calc( var(--base-hue) + var( --distance ) ), 100%, 50% ); --color-c: hsl( calc( var(--base-hue) + ( var( --distance ) * 2 ) ), 100%, 50% ); --color-d: hsl( calc( var(--base-hue) + ( var( --distance ) * 3 ) ), 100%, 50% ); }

Этот CSS дает нам тропическую цветовую схему.

Как использовать переменные в CSS

Кастомные свойства хорошо работают с медиа запросами, мы это увидим в последнем разделе.

Создание темной цветовой палитры через CSS переменные

С помощью кастомных свойств можно определять наборы переменных для темной и светлой темы сайта. Разберем пример ниже. Все HSL цвета можно заменить на переменные, определив их в :root:

:root{ /*...*/ --nav-bg-color: hsl(var(--primarycolor) , 50%, 50%); --nav-text-color: hsl(var(--primarycolor), 50%, 10%); --container-bg-color: hsl(var(--primarycolor) , 50%, 95%); --content-text-color: hsl(var(--primarycolor) , 50%, 50%); --title-color: hsl(var(--primarycolor) , 50%, 20%); --footer-bg-color: hsl(var(--primarycolor) , 93%, 88%); --button-text-color: hsl(var(--primarycolor), 50%, 20%); }

Для кастомных свойств использовались подходящие имена. Например, —nav-bg-color отсылает к цвету фона меню навигации, а —nav-text-color это цвет текста или переднего плана меню навигации. Теперь скопируем :root и добавим атрибут dark:

:root[theme='dark']{ /*...*/ }

Тема активируется, если добавить атрибут theme со значением dark к тегу html.

Теперь можно поиграться со значениями этих переменных. Например, можно уменьшить яркость HSL цветов, так можно добиться темной темы. Или же можно использовать CSS фильтры для инверсиии inver() и brightness(), которые часто используют для коррекции рендеринга изображений. Эти функции можно использовать и на других элементах.

Добавьте следующий код в :root[theme=’dark’]:

:root[theme='dark'] { --dark-hue: 240; --light-hue: 250; --primarycolor: var(--dark-hue); --nav-bg-color: hsl(var(--primarycolor), 50%, 90%); --nav-text-color: hsl(var(--primarycolor), 50%, 10%); --container-bg-color: hsl(var(--primarycolor), 50%, 95%); --content-text-color: hsl(var(--primarycolor), 50%, 50%); --title-color: hsl(--primarycolor, 50%, 20%); --footer-bg-color: hsl(var(--primarycolor), 93%, 88%); --button-text-color: hsl(var(--primarycolor), 50%, 20%); filter: invert(1) brightness(0.6); }

Invert() инвертирует все цвета в выбранных элементах (все элементы в нашем случае). Значение инверсии можно указать в процентах или числом. 100% или 1 – полная инверсия оттенка, насыщенности и яркости.

Brightness() фильтр делает элемент ярче или темнее. Значение 0 – полностью черный элемент.

Invert() может сделать некоторые элементы слишком яркими. Понизить тон можно через brightness(0.6). Темная тема с разными степенями затемнения:

Как использовать переменные в CSS

Давайте через JavaScript реализуем переключение темной и светлой темы по клику на кнопку Dark/Light. В HTML добавьте тег script перед закрывающим body:

const toggleBtn = document.querySelector("#toggle-theme"); toggleBtn.addEventListener('click', e => { console.log("Switching theme"); if(document.documentElement.hasAttribute('theme')){ document.documentElement.removeAttribute('theme'); } else{ document.documentElement.setAttribute('theme', 'dark'); } });

Document.documentElement – корневой элемент DOM документа, то есть html. Код проверяет наличие атрибута через метод hasAttribute(). Если атрибута нет, он добавляется со значением dark, что вызывает переключение темы на темную. В противном случае атрибут удаляется, что переключает тему на светлую.

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

Кастомные свойства и медиа запросы

Кастомные свойства можно использовать с медиа запросами. Например, можно с помощью кастомных свойств определять темную и светлую цветовую схему:

:root { --background-primary: hsl(34, 78%, 91%); --text-primary: hsl(25, 76%, 10%); --button-primary-bg: hsl(214, 77%, 10%); --button-primary-fg: hsl(214, 77%, 98%); } @media screen and ( prefers-color-scheme: dark ) { :root { --background-primary: hsl(25, 76%, 10%); --text-primary: hsl(34, 78%, 91%); --button-primary-bg: hsl(214, 77%, 98%); --button-primary-fg: hsl(214, 77%, 10%); } }

Также через кастомные свойства можно менять размер шрифта на экране или под печать:

:root { --base-font-size: 10px; } @media print { :root { --base-font-size: 10pt; } } html { font: var(--base-font-size) / 1.5 sans-serif; } body { font-size: 1.6rem; }

В этом примере мы используем единицы измерения, подходящие для медиа запросов. В обоих случаях мы задаем размер шрифта 10 единиц – пиксели для экрана и точки для печати. Также через значение —base-font-size: мы задаем начальный размер нашего корневого элемента html. С помощью единиц измерения rem мы задаем размер наших шрифтов относительно базового font size.

Кастомные свойства и JavaScript

Не забывайте, что кастомные свойства это такие же свойства CSS, и взаимодействовать с ними можно точно так же. Например, с помощью CSS.supports() API можно проверить поддержку браузером свойств:

const supportsCustomProps = CSS.supports('--primary-text: #000'); // Logs true to the console in browsers that support custom properties console.log(supportsCustomProps);

Через метод setProperty() можно задавать значения кастомных свойств:

document.body.style.setProperty('--bg-home', 'whitesmoke');

removeProperty() работает аналогично. Просто нужно в аргумент передать название кастомного свойства:

document.body.style.removeProperty('--bg-home');

Чтобы в JS получить значение кастомного свойства, используйте функцию var(), внутрь которой передайте название свойства:

document.body.style.backgroundColor = 'var(--bg-home)';

К сожалению, для определения кастомных свойств нельзя использовать квадратные скобки или camelCase на объекте style. То есть document.body.style.—bg-home и document.body.style[‘—bg-home’] работать не будут.

Кастомные свойства и компоненты

JS фреймворки React, Angular и Vue позволяют разработчикам создавать повторно используемые блоки HTML. Зачастую в этих блоках есть CSS, определенный на компонентном уровне.

Ниже пример компонента React на JSX, расширенном синтаксисе для JS:

import React from 'react'; /* Importing the associated CSS into this component */ import '../css/field-button.css'; class FieldButtonGroup extends React.Component { render() { return ( <div className="field__button__group"> <label htmlFor={this.props.id}>{this.props.labelText}</label> <div> <input type={this.props.type} name={this.props.name} id={this.props.id} onChange={this.props.onChangeHandler} /> <button type="submit">{this.props.buttonText}</button> </div> </div> ); } } export default FieldButtonGroup;

Наш React компонент импортирует CSS в JS файл. После компиляции контент field-button.css загружается инлайн. Ниже показан единственный способ, как это будет работать с кастомными свойствами:

.field__button__group label { display: block; } .field__button__group button { flex: 0 1 10rem; background-color: var(--button-bg-color, rgb(103, 58, 183)); /* include a default */ color: #fff; border: none; }

В примере выше мы задаем фоновый цвет кнопок через —button-bg-color. В случае отсутствия —button-bg-color применяется цвет по-умолчанию. Теперь мы можем задать значение —button-bg-color как в глобальных стилях так и в локальных через атрибу style.

Зададим значение как React prop. React prop или свойства работают аналогично атрибутам элемента. Это способ передачи данных в React компонент. В нашем случае мы добавим свойство buttonBgColor:

import FieldButtonGroup from '../FieldButtonGroup'; class NewsletterSignup extends React.Component { render() { // For brevity, we've left out the onChangeHandler prop. return ( <FieldButtonGroup type="email" name="newsletter" id="newsletter" labelText="E-mail address" buttonText="Subscribe" buttonBgColor="rgb(75, 97, 108)" /> ); } } export default NewsletterSignup;

Теперь обновим FieldButtonGroup:

class FieldButtonGroup extends React.Component { render() { /* In React, the style attribute value must be set using a JavaScript object in which the object keys are CSS properties. Properties should either be camelCased (e.g. backgroundColor) or enclosed in quotes. */ const buttonStyle = { '--button-bg-color': this.props.buttonBgColor }; return ( <div className="field__button__group"> <label htmlFor={this.props.id}>{this.props.labelText}</label> <div> <input type={this.props.type} name={this.props.name} id={this.props.id} onChange={this.props.onChangeHandler} /> <button type="submit" style={buttonStyle}> {this.props.buttonText} </button> </div> </div> ); } }

Мы добавили объект buttonStyle, в котором хранится название нашего кастомного свойства. Мы задаем значение этого свойства buttonBgColor и атрибут style для кнопки.

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

Однако в компонентной фронтенд архитектуре один компонент можно использовать во множестве контекстов различными командами. Можно даже делить компонент между клиентскими проектами. В таком случае вам может понадобиться как глобальная область применения с каскадированием, так и локальная область через атрибут style.

Кастомные свойства, заданные через атрибут style ограничивают свое действие до конкретного объекта компонента FieldButtonGroup. Но так как вместо обычного мы использовали кастомное свойство, мы все еще можем задать —button-bg-color в связанных стилях, а не в свойстве компонента.

Заключение

Кастомные свойства используют одну из лучших фич препроцессоров — переменные – и делает их нативными в CSS. С кастомными свойствами мы можем:

Создавать повторно используемые компоненты с возможностью установки тем

Легко настраивать padding, margin и шрифты под разные размеры экрана и медиа запросы

Привести все цвета в CSS к консистентности

Переменные можно много, где применить. В частности, они хорошо подходят системам с компонентной архитектурой. Надеюсь, вы теперь лучше понимаете, как пользоваться переменными или кастомными свойствами в CSS.

Автор: Tiffany Brown

Источник: www.sitepoint.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен