Переменные CSS — курс молодого бойца

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Переменные 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 и подпишитесь на обновления о книге.

image


  • Курс «Python для веб-разработки»
  • Профессия Веб-разработчик
  • Профессия Java-разработчик с нуля
  • Курс по JavaScript
  • Профессия iOS-разработчик с нуля
  • Профессия Android-разработчик с нуля

Eще курсы
  • Обучение профессии Data Science с нуля
  • Онлайн-буткемп по Data Science
  • Обучение профессии Data Analyst с нуля
  • Онлайн-буткемп по Data Analytics
  • Курс по Machine Learning
  • Курс «Математика и Machine Learning для Data Science»
  • Продвинутый курс «Machine Learning Pro + Deep Learning»
  • Курс по аналитике данных
  • Курс по DevOps
  • Профессия UX-дизайнер с нуля
  • Профессия Web-дизайнер


Читать еще


  • Данные внутри нас: Чем занимаются биоинформатики?
  • Machine Learning и Computer Vision в добывающей промышленности
Источник: https://habr.com/ru/company/skillfactory/blog/523130/


Интересные статьи

Интересные статьи

Привет! Мы сейчас всерьёз упарываемся по развитию внутреннего туризма. Обычно я пишу про эту часть работы не на Хабр, но на днях появился один крутой пример, по которому можно отследи...
Без бэкендеров не сможет нормально функционировать ни один сайт или приложение. Они проектируют алгоритмы взаимодействия сайта с пользователем и другими интернет-сервисами. Другим...
В конце марта наш медиахолдинг подготовил специальные антикризисные курсы о том, как организовать работу бизнеса в новых условиях. Мы разработали программы для руководителей компаний, бухгалтеров...
На вопросы отвечал Павел Зыков, СТО DomClick.ru ДомКлику скоро 5 лет. Давайте немного вспомним историю и заодно познакомимся. Компания была основана в 2015 году. Ты помнишь день, с которого вс...
Cтатья будет полезна тем, кто думает какую выбрать CMS для интернет-магазина, сравнивает различные движки, ищет в них плюсы и минусы важные для себя.