Зачем нужны кастомные свойства и как они работают? — спрашивает наш зритель Андрей. Они пришли, чтобы навсегда изменить CSS. Давайте разберёмся.

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

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

Как вообще работают препроцессоры? Вы пишете на каком-то языке, который внешне напоминает CSS, а иногда вообще не напоминает.

@mixin sass
  @if &
    &:hover
      color: tomato
  @else
    a
      color: plum

Потом это компилируется в настоящие стили. Переменные там — это такая сложная автозамена переменных на их значения. Sass, Less, Stylus, PostCSS-плагины — все они работают только так. Эти переменные существуют только в разработке, в браузере их уже нет.

.scss {
  $variable: value;
  color: $variable;
}

Если сравнить такое поведение с JavaScript, то становится очень обидно за CSS. В JS переменные живут прямо в браузере, их можно создавать и менять на лету. Тем не менее такие переменные и другие элементы программирования в CSS-препроцессорах получили огромную популярность. Уже почти не бывает больших проектов без препроцессоров.

К счастью, нашлись люди, недовольные такими куцыми переменными. После ряда черновиков и вариаций синтаксиса, Таб Аткинс написал спецификацию полноценных CSS-переменных, точнее, кастомных свойств. Эти переменные поддерживаются уже в 70% браузеров по миру и сильно меняют принцип написания стилей.

Кастомные кто? Объясняю. Помните, я говорил, что CSS не очень-то готов к переменным? Чтобы сохранить синтаксическую совместимость со старыми браузерами и не противоречить модели языка, было решено сделать не просто переменные с долларом в начале, а механизм создания собственных свойств для нужд разработчика. Ещё их переводят как «пользовательские» свойства, но с этим возникает путаница: кто здесь пользователь, а кто здесь разработчик? Сразу скажу, синтаксис у них немножко странный, но вы поймёте почему.

Например, у нас сейчас есть свойство box-shadow, чтобы отбрасывать тень. А раньше его не было, оно появилось первым в браузере Safari в 2008 году. Но появилось не просто так, а как -webkit-box-shadow, с префиксом, начинающимся с дефиса. То есть разработчики движка WebKit придумали своё свойство. Только потом, когда оно стало частью стандарта и появилось в других браузерах, префикс убрали.

.shady {
  -webkit-box-shadow:
    0 0 0 4px tomato;
  box-shadow:
    0 0 0 4px tomato;
}

Теперь вы тоже можете создавать собственные свойства, только не нужно указывать между дефисами название движка: дефис, дефис, название свойства. Давайте создадим свойство --box-shadow-color и зададим ему значение tomato. Чтобы использовать это значение в коде, нужно передать его в функцию var().

.shady {
  --box-shadow-color:
    tomato;
  box-shadow:
    0 0 0 5px
    var(--box-shadow-color);
}

Мы сейчас объявили новое свойство, которое потом можно повторно использовать снова и снова. А ещё свойства box-shadow-color никогда не было в природе и чтобы менять тени, например, по наведению, приходилось переписывать box-shadow целиком. А теперь по ховеру можно просто поменять значение переменной. Круто?

.shady {
  --box-shadow-color:
    tomato;
}
.shady:hover {
  --box-shadow-color:
    plum;
}

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

.shady {
  font-size:
    var(
      --font-size,
      12px
    );
}

Из-за того, что это кастомные свойства, а не просто доллары с автозаменой, они ведут себя как обычные свойства: наследуются вглубь для всех детей элемента и не видны между элементами-соседями. Чтобы переменную точно было видно во всём документе, её нужно задать самому корневому элементу html, но лучше даже :root, на случай если это корневой элемент svg.

:root {
  --font-size: 12px;
  --theme-color:
    tomato;
}

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

@media (min-width: 320px) {
  .shady {
    --font-size: 48px;
  }
}

Кастомные свойства можно использовать даже внутри функции calc(), которая посчитает результат выражения внутри. Уже не очень похоже на привычный CSS, правда? Стоит ли говорить, что все препроцессоры уже умерли от зависти, глядя на такое.

.shady {
  font-size:
    calc(
      var(--font-size)
      * 2
    );
}

Ещё кастомные свойства становятся идеальным транспортом для данных между скриптами и стилями. Например, вы можете динамически считать координаты мыши в JS и пробрасывать их в кастомные свойства через setProperty в нужный элемент.

element
  .style
  .setProperty(
    '--pointer-left',
    event.clientX
  );

Дальше в стилях уже можно решить: использовать их в top и left или transform: translate(). И наоборот: значение свойства можно получить в JS с помощью getPropertyValue.

И это я только кастомные свойства лапкой потрогал, дальше ещё куча интересного, что кардинально меняет работу со стилями. Читайте и смотрите дальше сами: статьи, видео и слайды в описании.

Кастомные свойства — это не border-radius, который либо делает красиво, либо нет. Бросаться всё переделывать на них пока рано, вёрстка может сильно поломаться в браузерах, которые их не поддерживают. Но уже пришло время пробовать и уметь.



«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.

ТелеграмПодкастБесплатные учебники

Читать дальше

Псевдоклассы валидации форм: делаем интерфейсы понятнее

Псевдоклассы валидации форм: делаем интерфейсы понятнее

Когда вы создаёте веб-форму, важно, чтобы пользователь сразу понимал, правильно ли он заполнил поля. Здесь на помощь приходят псевдоклассы :valid и :invalid. Эти инструменты, доступные в браузерах с 2018 года (согласно Baseline, статус «Widely Available»), позволяют стилизовать элементы формы в зависимости от того, проходят ли они валидацию. Представьте: пользователь вводит email, а поле подсвечивается зелёным, если всё верно, или красным, если что-то пошло не так. Это не только удобно, но и делает интерфейс интуитивно понятным даже для новичков.

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

Читать дальше
CSS
  • 15 августа 2025
Как сделать первую букву абзаца большой — буквица через ::first-letter

Как сделать первую букву абзаца большой — буквица через ::first-letter

Если сегодня мы воспринимаем веб как что-то само собой разумеющееся, то в начале 90-х годов страницы выглядели очень аскетично: просто текст, иногда ссылки, никаких визуальных изысков. Когда появился CSS, разработчики впервые получили возможность влиять на то, как отображается текст. Одной из первых «красивых» фич стал псевдоэлемент ::first-letter, появившийся ещё в спецификации CSS1 в 1996 году.

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

Читать дальше
CSS
  • 12 августа 2025
Лигатуры в CSS: как сделать текст аккуратнее

Лигатуры в CSS: как сделать текст аккуратнее

Если вы когда-нибудь присматривались к сочетаниям букв вроде «fi» или «fl» в хороших шрифтах, то, возможно, замечали, что они выглядят чуть иначе, чем при простом наборе. Буквы как будто «срастаются» в один знак, чтобы хвостики и точки не мешали друг другу. Это и есть лигатуры — особые глифы, которые шрифтовые дизайнеры создают для улучшения читаемости и эстетики текста. В вебе ими управляет свойство font-variant-ligatures.

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

Для фронтенд-разработчика важно знать, что лигатуры меняют только вид текста, но не его содержимое в DOM. Поиск, копирование, скрин-ридеры — всё продолжает работать корректно, ведь под капотом там по-прежнему две буквы, а не одна.

Читать дальше
CSS, Это база
  • 9 августа 2025
CSS-селекторы. Шпаргалка для новичков

CSS-селекторы. Шпаргалка для новичков

Селекторы — это шаблоны, которые используются для привязки стилевых свойств к элементам в документе. Вы можете задать стиль для всех элементов или сократить выбор с помощью определённого селектора.

Читать дальше
CSS
  • 8 августа 2025
CSS-градиенты в oklch

CSS-градиенты в oklch

Градиент — это плавный переход между двумя или более цветами, создаваемый с помощью функций linear-gradient() или radial-gradient(). Его используют в вебе для фонов, кнопок, рамок, декоративных элементов и даже в интерактивных эффектах при наведении.

Классические градиенты в CSS описываются в sRGB — привычном цветовом пространстве браузеров. Но у sRGB есть ограничения: некоторые переходы выглядят тусклыми или неравномерными, особенно если использовать яркие и сложные оттенки.

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

Читать дальше
CSS
  • 8 августа 2025
CSS :has() — проверка наличия потомков или соседних элементов

CSS :has() — проверка наличия потомков или соседних элементов

Представьте селектор, который выбирает элемент не по его собственным классам, а по тому, что происходит внутри него или рядом с ним. Так работает псевдокласс :has(): он позволяет применить стили к родителю (или соседу), если в нужном контексте нашёлся подходящий элемент. В результате — меньше вспомогательных классов, меньше JavaScript для «протаскивания» состояний наверх, и чище разметка.

Читать дальше
CSS
  • 6 августа 2025
Функция image() в CSS: цветовые плашки, вырезки из спрайтов и bidi-изображения

Функция image() в CSS: цветовые плашки, вырезки из спрайтов и bidi-изображения

Функция image() из модуля CSS Images Level 4 — это «умная» альтернатива url(), которая умеет больше: задавать направленность изображения (для языков слева-направо и справа-налево), вырезать фрагмент по медиасегменту #xywh и даже рисовать однотонную плашку как самостоятельный слой изображения. Звучит как швейцарский нож для бэкграундов — и так и есть. Но есть важная оговорка: на сегодня поддержка в браузерах минимальна, поэтому ниже мы покажем, как писать код «по-новому» и какие фолбэки использовать уже сейчас.

Читать дальше
CSS
  • 5 августа 2025
Всё самое важное о псевдоклассе :default

Всё самое важное о псевдоклассе :default

Псевдокласс :default — это способ стилизации элемента формы, выбранного по умолчанию. Он особенно полезен при работе с группами радиокнопок, чекбоксов или выпадающих списков, где важно визуально выделить стартовый (предустановленный) вариант. Такой подход делает интерфейс понятнее и помогает пользователю быстрее ориентироваться в выборе.

Доступно в Baseline в статусе «Widely Available» с 2022-07-15

Читать дальше
CSS
  • 4 августа 2025
Как работает единица измерения em в CSS

Как работает единица измерения em в CSS

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

Доступно в Baseline в статусе «Widely Available» с 2018-01-29

Читать дальше
CSS
  • 30 июля 2025
Как найти пустые элементы в CSS

Как найти пустые элементы в CSS

Псевдокласс :empty помогает находить пустые HTML-элементы, чтобы применять к ним стили или скрывать их. Это удобно для автоматической очистки интерфейса и улучшения UX без дополнительных классов или JavaScript.

Читать дальше
CSS
  • 29 июля 2025