Обложка статьи «Кастомные свойства в CSS. Часть 3: ограничения»

Кастомные свойства в CSS. Часть 3: ограничения

Рассказывает команда веб-факультета Яндекс.Практикума

Эта статья будет полезна, если вы уже знакомы с основами кастомных свойств в CSS: синтаксисом, особенностями контекста при использовании кастомных свойств и реактивностью при управлении через JavaScript. Понимаете, как применять контекст и фоллбэки для кроссбраузерности. Знаете, какая разница между кастомными свойствами и препроцессорными переменными. Если что-то из этого вам не знакомо, прочтите статью про основы кастомных CSS-свойств и про их особенности. Это достаточно исчерпывающее руководство, чтобы начать применять технологию в проектах. Но не хватает одной детали: используя любую технологию, нужно знать ограничения, которые она накладывает на разработку. Разберём, что кастомные свойства не умеют делать.

Кастомные свойства — это текст

Начнём с незамысловатых сложностей. Кастомные свойства — это текст. И любой текст с указанием кастомного свойства валиден внутри CSS-правил:

.block {
    background-color: #1e1e1e;
    background-color: Мой любимый цвет — var(--my-color);
}

Третью строку браузер посчитает валидной, при этом вторая не сработает:

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

Анимируются только в виде значений

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

/* Заведомо неправильный пример */

button {
    --scale: scale(1);
    transition: --scale .3s linear;
    transform: var(--scale);
}

button:hover {
    --scale: scale(1.2);
}

Этот пример кода — демонстрация хода мышления, который заведёт в тупик. Кастомное свойство подставляет значение, которое хранится в нём в виде текста.

Такой пример сработает:

button {
    --property: transform;
    --scale: scale(1);
    --duration: .3s;
    --timing-func: linear;
    transition: var(--property) var(--duration) var(--timing-func);
    transform: var(--scale);
}

button:hover {
    --scale: scale(1.2);
}

Не работают в медиазапросах

Несмотря на то, что кастомные свойства — текст, они не работают при объявлении медиазапросов. Это странно для тех, кто привык к переменным в препроцессорах.

Так сделать не получится:

:root {
    --tablet-width: 720px;
}

body {
    background-color: #1e1e1e;
}

@media screen and (max-width: var(--tablet-width)) {
    body {
        background-color: #000;
    }
}

Хотя аналогичный с виду код на SCSS скомпилируется в CSS и будет работать:

$tablet-width: 720px;

body {
    background-color: #1e1e1e;
}

@media screen and (max-width: $tablet-width) {
    body {
        background-color: #000;
    }
}

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

Так можно:

:root {
    --body-color: #1e1e1e;
}

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

@media screen and (max-width: 720px) {
    body {
        --body-color: #000;
    }
}

Проблемы фоллбэков и недостатки постпроцессинга

В статье про особенности кастомных свойств приведён пример кода, который не подойдёт для продакшена. Разберёмся, что с ним не так. Для этого вспомним, что делает POSTCSS, когда адаптирует код с кастомными свойствами под Internet Explorer.

Если кастомные свойства заданы на уровне корневого элемента, POSTCSS сделает фоллбэк:

:root {
    --some-perfect-color: #1e1e1e;
}

body {
    background-color: #1e1e1e; /* этот фоллбэк сделал POSTCSS */
    background-color: var(--some-perfect-color);
}

То же самое будет, если задать кастомное свойство на уровне блока, но указать альтернативное значение:

.block {
    --some-perfect-color: #1e1e1e;
    background-color: #1e1e1e; /* этот фоллбэк сделал POSTCSS */
    background-color: var(--some-perfect-color, #1e1e1e);
}

А так выглядит код, который не применим в реальных проектах, где нужна поддержка IE:

Если мы запустим постпроцессинг на файле style.css плагином postcss-custom-properties , получим такой код.

В нём есть проблемы:

1. Фоллбэки — тоже кастомные свойства. Всё, что идёт после запятой в обращении к кастомному свойству, POSTCSS считает альтернативным значением. Но IE не поймёт этого фоллбэка.

.page__title {
  font-size: 36px;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-blue);
  color: var(--title-color, var(--color-blue));
}

Можно немного «потанцевать с бубном» и добиться нужного фоллбэка, если написать в исходном файле что-то такое:

.page__title {
  font-size: 36px;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--title-color, var(--color-blue, #005cff));
}

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

2. Переопределённым кастомным свойствам невозможно прописать фоллбэки.

Посмотрим код из результата постпроцессинга:

.page__section_type_canceled {
  --title-color: var(--color-red);
  --border-color: var(--color-red);
}

Он идентичен исходному коду — ничего не произошло. POSTCSS-плагин никак не разгадает нашу задумку с наследованием кастомного свойства от модификатора. Чтобы всё заработало, POSTCSS должен просмотреть всех наследников блока с модификаторами в DOM и написать ещё два CSS-блока для вложенных элементов. Это за гранью его возможностей.

В общем, если вы хотите использовать кастомные свойства, применяя принципы каскада, про Internet Explorer стоит забыть.

Итоги

Работа над кастомными свойствами в CSS продолжается и скоро мы увидим новые фишки. Уже сейчас Google Chrome в 85-й версии экспериментирует со свойством property, разработанным проектом Houdini. Это направление кажется многообещающим: в кастомных свойствах появятся типы и исходные значения. Если хотите овладеть кастомными CSS-свойствами ещё больше, ознакомьтесь с документацией. И практикуйтесь. Много практикуйтесь.

Хинт для программистов: если зарегистрируетесь на соревнования Huawei Honor Cup, бесплатно получите доступ к онлайн-школе для участников. Можно прокачаться по разным навыкам и выиграть призы в самом соревновании.

Перейти к регистрации