CSS Custom Properties. CSS-переменные vs Sass-переменные

CSS Custom Properties. CSS-переменные vs Sass-переменные

CSS-переменные — это пользовательские CSS-свойства (Custom Properties), экспериментальная технология, находящаяся на третей стадии редакторского черновика (Editor’s Draft, о котором уже упоминалось в статье про CSS вложенности. Но не смотря на это, пользовательские CSS-свойства поддерживаются в большинстве современных и популярных браузерах. Поэтому данный синтаксис вполне можно применять как есть, но если вам все-таки нужно осуществить поддержку и в более старых браузерах, то необходимо использовать плагин postcss-custom-properties.

Использование

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

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

  • Первый параметр — название нужной переменной.
  • Второй параметр — фолбек; переменная или значение, которое будет применено в случае, если переменная, переданная первым параметром, недоступна (необязательный параметр).

Они могут быть объявлены глобально и локально, и будут доступны только там, где определены.

Глобальное объявление

Для того, чтобы объявить переменную глобально, необходимо определить ее к элементу :root (корневой элемент в дереве). Это будет означать, что она станет доступна для любых элементов в документе.

Пример:

:root {
  --color-mine-shaft: #333;
}
.title {
  color: var(--color-mine-shaft);
}

Локальное объявление

Объявлять переменную можно не только глобально, но и в конкретном элементе. Тогда она будет доступна только внутри него и для всех дочерних элементов:

.plate {
  --color-malibu: #699dff;
}

.plate p {
  color: var(--color-malibu);
}

В следующем примере переменная --color-mine-shaft не применится к элементу .title, т.к. она объявлена внути .list, а .title расположен не внутри него.

<div class="content">
  <div class="title">
    Заголовок
  </div>
  <ul class="list">
    <li class="list__item">
      Пункт 1
    </li>
    <li class="list__item">
      Пункт 2
    </li>
    <li class="list__item">
      Пункт 3
    </li>
  </ul>
</div>
.title {
  font-size: 30px;
  color: var(--color-mine-shaft); /* не применится! */
}

.list {
  --color-mine-shaft: #333;
  list-style-type: square;
}

.list__item {
  color: var(--color-mine-shaft);
}

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

<div class="post">
  <div class="title">
    Заголовок
  </div>
  <div class="content">
    Контент
  </div>
</div>
.title {
  font-size: 50px;
  font-weight: 700;
}

.content {
  font-size: var(--post-font-size); /* использование */
}

.post {
  --post-font-size: 20px; /* объявление */
}

Использование с PostCSS

Как уже говорилось ранее, чтобы включить поддержку CSS-переменных в старых браузерах, например, Internet Explorer, необходимо применять данный синтаксис вместе с плагином postcss-custom-properties.

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

Для того, что запускать PostCSS в командной строке необходимо установить следующие пакеты:

npm install -D postcss postcss-cli

И непосредственно сам плагин postcss-custom-properties:

npm install -D postcss-custom-properties

Далее в файле postcss.config.js подключаем установленный пакет:

module.exports = {
  plugins: [
    require('postcss-custom-properties')
  ]
};

Использование с Gulp

Для добавления PostCSS в ваш проект нужно воспользоваться следующей командой:

npm install -D gulp-postcss

И в gulpfile.js создать задачу для использования кастомных CSS-свойств:

let postcss = require('gulp-postcss');
let postcssCustomProperties = require('postcss-custom-properties');

gulp.task('css', () => {
  gulp.src('./src/*.css')
    .pipe(postcss([
      postcssCustomProperties(/* опции плагина */)
    ]))
    .pipe(gulp.dest('build/css'));
});

где:

  • gulp.src('./src/*.css') — путь в главному файлу стилей.
  • gulp.dest('build') — пусть, по которому будет располагаться скомпилированный файл стилей.

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

CSS-переменные vs переменные в препроцессорах

Большинство разработчиков впервые узнали о существовании переменных для стилей именно благодаря препроцессорам, таким как: Sass, Less, Stylus и др. Но в настоящее время поддержка нативных переменных становится более распространенной, да и к тому же, выясняется, что они имеют гораздо больше возможностей и значительно превосходят препроцессорные.

SCSS-переменные просто создавать и использовать, и это в принципе единственный их плюс:

// создание
$font-family-pt-sans: "PT Sans", sans-serif;

// использование
font-family: $font-family-pt-sans;

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

  • Переменные в препроцессах требуют компиляции, после чего становятся «‎‎вшитыми» в итоговый файл стилей и недоступными в браузере. А пользовательские свойства ведут себя противоположно, как бы становясь частью CSSOM (CSS Object Model).

Пример:

:root {
  --post-font-size: 20px;
  --color-red: red;
}

.post {
  font-size: var(--post-font-size);
  color: var(--color-red);
}

В результате, в браузере мы увидим, что эти переменные сохранились, и доступны для нас:

CSS-переменные
  • Нативные переменные более «живые», изменяемые. Например, в медиа запросах или во вложенных элементах можно перезаписывать их значения, в то время, как в препроцессорах, они больше похожи на константы, то есть статичные выражения.

  • С помощью JavaScript можно получить доступ к пользовательским свойствам, а к препроцессорным нельзя.

  • Нативные переменные являются каскадными и наследуемыми, как свойства.

Доступ с помощью JavaScript

CSS-переменные являются частью CSSOM, а как мы знаем, ко всему, что в нем находится, можно получить доступ с помощью JavaScript. Это пригождается, когда необходимо динамически изменять значения. К примеру, в настоящее время очень актуально наличие «темной темы» на сайтах. Чаще всего это представляет из себя переключатель, с помощью которого пользователь может переключаться на темный режим для комфортного чтения в ночное время суток. То есть, в данном случае происходит динамическая смена переменных цветов.

Основные действия, которые нам нужны для работы с переменными — создание, получение и перезапись. Все достаточно просто. Давайте рассмотрим соответствующие примеры.

Пусть нам дан следующий файл стилей, в котором есть несколько переменных:

:root {
  --post-font-size: 20px;
  --color-red: red;
  --color-blue: blue;
}

.post {
  font-size: var(--post-font-size);
  color: var(--color-red);
}

.title {
  color: var(--color-blue);
}

Прежде всего нужно будет обращаться к элементу, в котором объявлены переменные (:root). Для удобства сохраним его:

let root = document.querySelector(':root');

Получение — getPropertyValue

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

root.style.getPropertyValue('--post-font-size');

Таким образм мы получим значение переменной:

console.log(root.style.getPropertyValue('--post-font-size'));

// выведет: 20px

Создание и переопределение — setProperty

Для того, чтобы создать новое свойство или переопределить его значение, есть метод setProperty. Он принимает три параметра:

  • Строка — имя CSS-свойства, которое будет модифицироваться (или создаваться, если его еще нет)(обязательный).
  • Строка — новое значение (обязательный).
  • Строка — приоритетность (опциональный). Может иметь значения: important и undefined.
root.style.setProperty('--post-font-size', '60px');
root.style.setProperty('--post-border-width', 'solid 1px #000');

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