Статьи

Практическое руководство по CSS-переменным (пользовательские свойства)

Этот пост был обновлен в августе 2018 года.

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

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

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

Давайте погрузимся прямо в!

Что такое CSS-переменные?

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

Например, рассмотрим следующий фрагмент JavaScript:

let number1 = 2; let number2 = 3; let total = number1 + number2; console.log(total); // 5 number1 = 4; total = number1 + number2; console.log(total); // 7 

number1 и number2 — две переменные, которые хранят числа 2 и 3 соответственно.

total также является переменной, которая хранит сумму переменных number1 и number2 , в данном случае получая значение 5. Вы можете динамически изменять значение этих переменных и использовать обновленное значение в любом месте вашей программы. В приведенном выше фрагменте я обновляю значение с номера 1 до 4, и когда я снова выполняю сложение, используя те же переменные, результат, сохраненный внутри total , больше не 5, а 7.

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

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

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

Есть ли преимущества использования CSS-переменных?

Преимущества использования переменных в CSS мало чем отличаются от преимуществ использования переменных в языках программирования.

Вот что спецификация должна сказать по этому поводу:

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

Спецификация W3C .

Другими словами:

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

В чем разница между переменными CSS и переменными препроцессора?

Одним из способов использования гибкости переменных при стилизации веб-сайтов является использование препроцессоров, таких как Sass и Less .

Препроцессоры позволяют устанавливать переменные и использовать их в функциях, циклах, математических операциях и т. Д. Означает ли это, что переменные CSS не имеют значения?

Не совсем, в основном потому, что переменные CSS отличаются от переменных препроцессора.

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

Это означает, что вы можете обновить CSS-переменные в документе таблицы стилей, внутри встроенных атрибутов стиля и SVG-атрибутов представления, или выбрать управление ими на лету с помощью JavaScript. Вы не можете делать это с переменными препроцессора. Это открывает целый мир возможностей!

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

Переменные CSS: синтаксис

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

 --my-cool-background: #73a4f4; 

Вы ставите перед пользовательским свойством две черточки и присваиваете ему значение, как и в обычном свойстве CSS В приведенном выше фрагменте я присвоил значение цвета пользовательскому свойству --my-cool-background .

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

 var(--my-cool-background) 

Пользовательское свойство находится в области выбора CSS, а часть var() используется в качестве значения реального свойства CSS:

 :root { --my-cool-background: #73a4f4; } /* The rest of the CSS file */ #foo { background-color: var(--my-cool-background); } 

Приведенный выше фрагмент --my-cool-background пользовательское свойство --my-cool-background к псевдоклассу :root , что делает его значение доступным глобально (оно соответствует всему элементу <html> ). Затем он использует функцию var() чтобы применить это значение к свойству background-color контейнера с идентификатором foo , который, как следствие, теперь будет иметь красивый светло-синий фон.

Это не все. Вы можете использовать одно и то же приятное значение светло-голубого цвета для стилизации других цветовых свойств нескольких элементов HTML, например, color , border-color и т. Д., Просто извлекая значение пользовательского свойства с помощью var(--my-cool-background) и применяя его к соответствующему свойству CSS (конечно, я рекомендую немного подумать над соглашением об именах для переменных CSS, прежде чем что-то запутать):

 p { color: var(--my-cool-background); } 

Вы также можете установить значение переменной CSS с другой переменной CSS. Например:

 --top-color: orange; --bottom-color: yellow; --my-gradient: linear-gradient(var(--top-color), var(--bottom-color)); 

Приведенный выше фрагмент создает переменную --my-gradient и устанавливает для нее значение переменных --top-color и --bottom-color для создания градиента. Теперь вы можете изменить свой градиент в любое время, где бы вы ни решили использовать его, просто изменив значения ваших переменных. Нет необходимости преследовать все экземпляры градиента по всем вашим таблицам стилей.

Вот живая демонстрация CodePen.

Наконец, вы можете включить одно или несколько резервных значений с вашей переменной CSS. Например:

 var(--main-color, #333); 

В приведенном выше фрагменте # 333 является запасным значением. Если запасные варианты не включены, в случае недопустимых или неустановленных пользовательских свойств вместо этого будет применяться унаследованное значение.

Переменные CSS чувствительны к регистру

В отличие от обычных свойств CSS, переменные CSS чувствительны к регистру.

Например, var(--foo) и var(--FOO) ссылаются на два различных пользовательских свойства, --foo и --FOO соответственно.

Переменные CSS подчиняются каскаду

Как и обычные свойства CSS, переменные CSS наследуются. Например, давайте определим пользовательское свойство со значением blue :

 :root { --main-color: blue; } 

Все элементы внутри корневого элемента <html> которому вы решили применить переменную --main-color , будут наследовать значение blue .

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

 :root { --main-color: blue; } .alert { --main-color: red; } p { color: var(--main-color); } 
 <--! HTML --> <html> <head> <!-- head code here --> </head> <body> <div> <p>blue paragraph.</p> <div class="alert"> <p>red paragraph.</p> </div> </div> </body> </html> 

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

Абзац внутри элемента div с классом .alert будет красным, потому что его значение цвета наследуется от локальной переменной --main-color , которая имеет значение red .

На сегодня хватит правил, давайте приступим к кодированию!

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

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

Допустим, вы хотите, чтобы у ваших SVG-значков был другой цвет в соответствии с родительским контейнером, внутри которого они размещены. Вы можете разместить свои переменные локально внутри каждого родительского контейнера, установить для них нужный цвет, а значок внутри каждого контейнера унаследует соответствующий цвет от своего родителя.

Вот соответствующие фрагменты:

 /* inline SVG symbol for the icon */ <svg> <symbol id="close-icon" viewbox="0 0 200 200"> <circle cx="96" cy="96" r="88" fill="none" stroke="var(--icon-color)" stroke-width="15" /> <text x="100" y="160" fill="var(--icon-color)" text-anchor="middle" style="font-size:250px;">x</text> </symbol> </svg> /* first instance of the icon */ <svg> <use xlink:href="#close-icon" /> </svg> 

В приведенной выше разметке используется <symbol> , который позволяет создавать невидимую версию графики SVG. Затем код создает видимую копию той же графики с <use> . Этот метод позволяет создавать любое количество значков и индивидуально настраивать их по своему вкусу, просто ссылаясь на элемент <symbol> по его идентификатору ( #close-icon ). Это удобнее, чем повторять один и тот же кусок кода снова и снова, чтобы воссоздать изображение. Если вам нужно освежить эту технику, Массимо Кассандро предлагает краткое руководство по его иконам «Создайте свой собственный SVG» .

Обратите внимание на значение свойства stroke внутри элемента circle и свойства fill внутри текстового элемента символа SVG: они оба применяют переменную CSS, то есть --icon-color , которая определена в селекторе :root внутри CSS документ, вот так:

 :root { --icon-color: black; } 

Вот как выглядит значок в этой точке:

Внешний вид значка SVG по умолчанию.

Если вы теперь поместите значок SVG внутри разных элементов контейнера и локализуете свою переменную внутри селектора каждого родительского элемента с другим значением цвета, у вас будут значки разных цветов без необходимости добавления каких-либо дополнительных правил стиля. Здорово!

Чтобы показать это, давайте .success экземпляр того же значка внутри div с классом .success .

HTML:

 <div class="success"> <svg> <use xlink:href="#close-icon" /> </svg> </div> 

Теперь локализуйте переменную --icon-color , присвоив ей зеленое значение внутри селектора .success и проверьте результат.

CSS:

 .success { --icon-color: green; } 

Цвет значка теперь зеленый:

SVG значок успеха с другим цветом.

Посмотрите полную демонстрацию ниже:

Как вы можете использовать CSS-переменные с @keyframes Animation

Переменные CSS могут работать с CSS-анимацией, как с обычными элементами HTML, так и со встроенными SVG. Просто не забудьте определить пользовательские свойства внутри селектора, который нацеливается на элемент, который вы хотите анимировать, и обращаться к ним с помощью функции var() внутри блока @keyframes .

Например, чтобы анимировать элемент <ellipse> с классом .bubble внутри SVG-графики, ваш CSS может выглядеть следующим образом:

 .bubble { --direction-y: 30px; --transparency: 0; animation: bubbling 3s forwards infinite; } @keyframes bubbling { 0% { transform: translatey(var(--direction-y)); opacity: var(--transparency); } 40% { opacity: calc(var(--transparency) + 0.2); } 70% { opacity: calc(var(--transparency) + 0.1); } 100% { opacity: var(--transparency); } } 

Обратите внимание, как вы можете выполнять вычисления с помощью функции var() с помощью CSS calc() , что добавляет вашему коду еще большую гибкость.

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

Вот полная демонстрация CodePen, с которой вы можете поэкспериментировать:

Как вы можете манипулировать переменными CSS с помощью JavaScript

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

Допустим, у вас есть CSS-переменная --left-pos со значением 100px для класса .sidebar в вашем CSS-документе:

 .sidebar { --left-pos: 100px; } 

Получение значения --left-pos из вашего кода JavaScript будет выглядеть так:

 // cache the element you intend to target const sidebarElement = document.querySelector('.sidebar'); // cache styles of sidebarElement inside cssStyles const cssStyles = getComputedStyle(sidebarElement); // retrieve the value of the --left-pos CSS variable const cssVal = String(cssStyles.getPropertyValue('--left-pos')).trim(); // log cssVal to print the CSS // variable's value to the console: 100px console.log(cssVal); 

Чтобы установить переменную CSS с помощью JavaScript, вы можете сделать что-то вроде этого:

 sidebarElement.style.setProperty('--left-pos', '200px'); 

Приведенный выше фрагмент --left-pos устанавливает значение переменной --left-pos для элемента боковой панели в --left-pos .

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

Посмотрите демонстрацию CodePen ниже, где вы можете в интерактивном режиме переключать боковую панель и изменять свойство режима наложения и цвет фона, используя только переменные CSS и JavaScript:

Браузерная поддержка переменных CSS

За исключением IE11 (который не поддерживает переменные CSS), все основные браузеры имеют полную поддержку переменных CSS .

Один из способов, которым ваш код может обслуживать не поддерживающие браузеры, — это использовать блок @supports с фиктивным условным запросом:

 section { color: gray; } @supports(--css: variables) { section { --my-color: blue; color: var(--my-color, 'blue'); } } 

Учитывая, что @supports работает в IE / Edge, это поможет. Если вы также воспользуетесь резервными значениями внутри функции var() , ваш код будет еще более надежным и изящно ухудшится в менее функциональных браузерах.

В результате в Chrome и других поддерживающих браузерах текст внутри элемента <section> будет синим:

Как приведенный выше код отображается в последней версии браузера Chrome с поддержкой CSS-переменных.

IE11, который не поддерживает переменные CSS, отображает страницу с серым текстом:

Как приведенный выше код отображается в IE11, браузере без поддержки переменных CSS.

Проверьте живую демонстрацию:

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

В этом случае вы могли бы выбрать PostCSS с помощью cssnext , который позволяет вам писать передовой код CSS и делать его совместимым с не поддерживающими браузерами (немного как транспортеры для JavaScript). Если вам интересно узнать о PostCSS, SitePoint Premium предоставляет всем своим участникам отличный видеокурс по этой теме.

Ресурсы

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

Fun Demos

Чего же ты ждешь? Попробуйте CSS-переменные и дайте мне знать, что вы думаете в комментариях!