Мы принимаем к оплате:
«Подарочный сертификат» от нашего Учебного Центра – это лучший подарок для тех, кто Вам дорог! Оплате обучение и подарите Вашим родным и близким обучение по любому из курсов!!!
«Сертификат на повторное обучение» дает возможность повторно пройти обучение в нашем Учебном Центре со скидкой 1000 рублей!
А также:
Переменные в css
Css переменные : описание и примеры использования.
Здравствуйте друзья, на связи Шевченко Вячеслав, и сегодня у меня не большой, но интересный пост. Вы когда нибудь сталкивались с проблемой разрастания проекта, и организацией css кода? Думаю ответ однозначно ДА, если НЕТ, то у вас все впереди.
Когда проект начинает расти, его CSS обычно становится громоздким, и тяжело поддерживаемым. Чтобы решить эту проблему, разработчики CSS ввели переменные, они уже поддерживаются популярными браузерами. Это дает возможность легко работать с повторениями стилей.
Знающие и бывалые верстальщики, могут возразить и сказать «Переменные уже давно в SASS и LESS!!». Да, я не спорю, но это препроцессоры и они нуждаются в компиляции перед использованием, а нативные переменные CSS работают прямо в браузере! Разве это не круто?
Видео урок
Объявление и использование CSS переменных
Переменные в файле используют ту же область видимости, что и другие правила в CSS. Конечно удобнее всего, когда они глобальные. Для этого нужно объявлять их внутри псевдо-класса :root.
:root{ --color-blue: #2437e2; }Чтобы получить доступ к переменной нужно использовать синтаксис var(...). Обратите внимание, что имена переменных чувствительны к регистру. К примеру --color-blue не будет равен --COLOR-BLUE.
.container{ background-color: var(--color-blue); }background-color: var(--color-blue); |
Немного о поддержке
Сейчас переменные работают в Firefox и Chrome последней версии. Актуальную информацию по поддержке можно получить здесь. Ниже я приведу несколько примеров, которые хорошо продемонстрируют типичные случаи использования CSS-переменных. Если у вас не работают примеры, убедитесь что у вас браузер последних версий.
Цвета темы оформления
Переменные очень полезны когда вам нужно использовать свойства неоднократно. Здесь хорошим примером будет цветовая схема оформления. Вместо того чтобы копировать цвет от правила к правилу, мы можем просто поместить его в переменную и брать его оттуда.
И когда по каким-то причинам нужно будет изменить цвет темы, или создать новый скин, вы можете изменить цвет только в одном месте, но изменения повлияют на все страницы сайта.
Понятные имена для свойств
Вторым удобным способом использования переменных является создание неких пресетов, когда мы не хотим запоминать длинное значение свойства, например для transform, box-shadow и font.
Поместив значение свойства в переменную, мы можем вызвать его, используя понятные имена.
Динамическое изменение значений переменных
Когда каст свойство объявлена несколько раз , то тогда не учитывается низкое объявление в каскадном уровне стилей.
Пример ниже показывает как легко динамично манипулировать свойствами , при этом оставляя код чистым.
Еще несколько советов
Как вы видите, переменные в CSS — достаточно простой инструмент для использования и не требует много времени на его освоение. И еще пару вещей, которые вам нужно знать:
Функция var() принимает два аргумента, второй будет использоваться, если с переменной что-то не так:
width: var(--custom-width, 20%);width: var(--custom-width, 20%); |
Также можно комбинировать переменные:
--base-color: #f93ce9; --background-gradient: linear-gradient(to top, var(--base-color), #444);--background-gradient: linear-gradient(to top, var(--base-color), #444); |
Так же можно переменные использовать с функцией calc(), ранее я писал о ней на сайте, обязательно прочтите статью если вы не знакомы с calc().
--container-width: 1000px; max-width: calc(var(--container-width) / 2);--container-width: 1000px;max-width: calc(var(--container-width) / 2); |
Вот и все, теперь вы знаете как использовать переменные в CSS, только не увлекайтесь сильно переменными в рабочих проектах, так как поддержка очень слабая.
Если вам статья была интересна и полезна, поделитесь ей в социальных сетях. Так же подписывайтесь на наши группы в facebook и vkontakte. До встречи в новых статьях.
comments powered by HyperCommentsПеременные в CSS
Если вы разработчик, то вы точно хорошо знакомы с переменными, и возможно, они одни из ваших лучших друзей. По определению, переменная — это временное хранилище, которое содержит некое значение величины или информации. Но каким образом это относится к тому CSS, который мы все знаем? Год назад на Хабре был пост о планируемых новшествах в CSS, которые были оглашены членом рабочей группы CSS и команды Google Chrome. Среди этих новшеств было введение поддержки переменных. И вот, буквально на днях, поступили новости о выходе первого релиза рабочего черновика CSS Переменных (CSS Variables).
Почему CSS переменные?
Переменные в CSS — эта та штука, о которой народ спрашивал и хотел довольно долгое время. Подумайте обо всех этих цветах (colors), высотах (heights), ширинах (widths) и размерах (sizes): как бы было прекрасно объявить их всего лишь один раз. И наконец, пришло время того, чего мы так долго ждали: писать меньше, но делать больше.Установившиеся практики в CSS
Когда люди просят об объявлении переменных цвета в css (color), добавление комментариев в верней части CSS-файла было чем-то вроде симуляции поведения переменных: /*-------------------------- link color: #99D1FF (light blue) box color: #555 (dark gray) --------------------------*/ Позже, чтобы обновить значения, приходилось делать поиск и замену.Как это делается в LESS/Sass
Идея использовать переменные для таблицы стилей было одной из тех причин, по которым появились LESS и Sass.LESS
Sass
Как это будет работать теперь
Прежде всего, не забывайте, что это ни один из браузеров пока не поддерживает. Но это то, как оно будет работать в будущем:var-foo для определения, var(foo) для использования.
Следуя черновикам:Любое имя свойства, начинающееся с префикса “var-” является свойством переменной. (Any property name starting with the prefix “var-” is a variable property)Пример
Следующее правило декларирует имя свойства “var-header-color” для элемента root и присваивает для него значение “#99D1FF”: :root { var-header-color: #99D1FF; } Далее, его значение может передаваться с помощью переменной “header-color”: h2 { color: var(header-color); } Использование переменных цвета в определении градиентов также может быть очень полезным. Вам всего лишь нужно будет заменить значение переменных, и вуаля: все градиенты обновились. Звучит довольно круто, как по мне.Также, при создании макета, применив переменные и функцию calc() можно сделать интересные вычисления.
Вывод
CSS не является языком программирования, но он и не должен быть сложным. Однако, я думаю вы согласитесь, что использование CSS переменных поможет избежать дублирования и позволит создавать более гибкие таблицы стилей.Теперь, когда вышел в свет первый модуль CSS переменных, мы с нетерпением ждем поддержку их браузерами в ближайшем будущем.
Теги:Переменные в CSS
По мере роста проекта его CSS файлы разрастаются и засоряются. Справиться с этим помогут CSS переменные, они дают возможность повторно использовать повторяющиеся CSS свойства. Раньше переменные можно было использовать только в Less или Sass, но это препроцессоры и требуют компиляции перед использованием. Теперь переменные доступны в чистом CSS.
Объявление и использование переменных в CSS
На переменные в CSS распространяются те же ограничения и правила наследования, что и на обычные CSS правила. Самый простой способ использовать их — объявить их глобально в псевдо-классе :root, так все остальные селекторы смогут его наследовать.
:root{ --awesome-blue: #2196F3; }Для доступа к значению переменной надо использовать конструкцию var(…). Обратите внимание, что имена зависят о регистра, то есть —foo != —FOO.
.some-element{ background-color: var(--awesome-blue); }Поддержка
На данный момент Firefox поддерживает переменные в CSS. В Google Chrome начиная с версии 49 это возможность включена, если вы используете версию 48 или более старую, то вы можете вручную включить поддержку, перейдя на страницу chrome://flags/ и включить Enable experimental Web Platform features.
Пример 1 — Цветовые схемы
Переменные в CSS полезны, когда вам надо применить одно и то же свойство для разных элементов, например, повторяющиеся цвета в теме. Вместо того, чтобы копировать один и тот же цвет везде где он нужен, мы можем использовать переменную.
Теперь, если заказчик захотел поменять цвет на странице, мы можем изменить весь стиль поменяв одну строку (строку объявления переменной). Без переменных нам пришлось бы менять все места, где используется этот цвет.
Пример 2 — Понятные названия для сложных свойств
Еще одна замечательная возможность, которую дают CSS переменные — спрятать сложное свойство за коротким понятным именем. Хороший пример — CSS свойства с несколькими параметрами, например: box-shadow, transform и font.
Объявив переменную с понятным именем мы сможем использовать её не тратя время на разбор сложного свойства.
Пример 3 — Динамические переменные
Когда переменная объявлена несколько раз, к ней применяются стандартные CSS правила наследования. Следующий пример демонстрирует как можно динамически управлять свойствами в зависимости от действий пользователя, при этом сохранить краткий и чистый код.
Наведите на зеленый и на синий блоки.
Заключение
Как видите переменные довольно просты в использовании и их определенно стоит попробовать. Рассмотрим еще пару вещей, на которые стоит обратить внимание:
- Функция var() имеет второй параметр, который будет использован в качестве значения, если переменная вызовет ошибку: width: var(--custom-width, 20%);
- При объявлении собственного правила так же можно использовать переменные: --base-color: #f93ce9; --background-gradient: linear-gradient(to top, var(--base-color), #444);
- Переменные можно использовать с еще одним нововведением в CSS — функцией calc(). Однако работает это пока только в Firefox: --container-width: 1000px; max-width: calc(var(--container-width) / 2);
На этом все! Попробуйте использовать CSS переменные, но пока избегайте их в серьезных проектах.
Преимущества CSS-переменных (пользовательских CSS-свойств)
Перевод статьи Why I’m Excited About Native CSS Variables с сайта philipwalton.com, опубликовано на css-live.ru с разрешения автора — Филипа Уолтона.
Несколько недель назад CSS-переменные — точнее, пользовательские CSS-свойства — стали доступны в Chrome Canary за флагом «Экспериментальные возможности веб-платформы».[1]
Как только один из разработчиков Chrome Эдди Османи написал о новинке в Твиттере, на него неожиданно обрушилась масса недовольства, злобы и скептицизма. По крайней мере, неожиданно для меня, учитывая, как меня эта возможность восхитила.
После беглого просмотра откликов стало ясно, что 99% процентов жалоб сосредоточены вокруг двух моментов:
- «Страшный» и «многословный» синтаксис
- Уже есть переменные в Sass, зачем что-то еще?
Хотя я признаю, что синтаксис мне тоже не нравится, важно понимать, что он выбран не случайно. Участники рабочей группы CSS долго обсуждали синтаксис, и им пришлось выбрать то, что совместимо с грамматикой CSS и не будет конфликтовать с будущими дополнениями языка.
А что касается сравнения CSS-переменных с переменными Sass, то вот в чем, по-моему, кроется главное непонимание:
«Родные» CSS-переменные и не пытались лишь копировать то, что уже по силам CSS-препроцессорам. На самом деле, если почитать некоторые обсуждения исходной идеи, вы увидите, что в первую очередь «родные» CSS-переменные задумывались ради возможности делать то, что недоступно препроцессорам!
CSS-препроцессоры — фантастические инструменты, но переменные в них статичны и ограничены своей областью видимости. «Родные» CSS-переменные — напротив, совсем другой вид переменных: они динамические, а их видимость привязана к DOM. Пожалуй, название «переменные» для них только сбивает с толку. На самом деле это CSS-свойства, что дает им совершенно другой спектр возможностей и позволяет им решать совсем другие задачи.
В этой статье я расскажу о некоторых штуках, которые можно сделать с пользовательскими CSS-свойствами, а с переменными препроцессоров — нельзя. А также покажу несколько новых приемов разработки, ставших возможными благодаря этим свойствам. Наконец, я поделюсь соображениями, почему в будущем мы скорее всего будем пользоваться и переменными препроцессоров, и пользовательскими свойствами, чтобы взять лучшее от обоих.
Примечание: эта статья — не введение в пользовательские CSS-свойства. Если вы не слыхали про них или не в курсе, как они работают, советую сначала ознакомиться с ними.
Ограниченность препроцессорных переменных
Прежде чем продолжить, хочу подчеркнуть, что мне вправду нравятся CSS-препроцессоры, я использую их во всех своих проектах. Некоторые возможности препроцессоров просто замечательны, и даже если вы знаете, что в конечном итоге они лишь выдают простой CSS, они всё равно порой кажутся чем-то волшебным.
Но всё же, как у любого инструмента, у них есть свои ограничения, и иногда, когда в игру вступает динамика, эти ограничения оказываются неожиданными, особенно для новичков.
Переменные препроцессоров не динамичны
Пожалуй, самый частый пример ограниченности препроцессоров, который ставит в тупик начинающих — то, что Sass не умеет определять переменные или использовать @extend внутри медиавыражения. Раз статья о переменных, я сосредоточусь на первом:
$gutter: 1em; @media (min-width: 30em) { $gutter: 2em; } .Container { padding: $gutter; }Если скомпилировать этот код, получится вот что:
.Container { padding: 1em; }Как видите, блок медиавыражения просто оказался отброшен, и присвоение переменной в нем проигнорировано.
Хотя теоретически заставить работать условные объявления переменных в Sass возможно, это будет крайне непросто и потребует перечисления всех возможных вариантов — отчего размер итогового CSS начнет расти по экспоненте.
Поскольку менять переменную на основе соответствующего правила @media нельзя, единственный выход — заводить уникальную переменную на каждое медиавыражение, и писать код для каждого варианта отдельно. Подробнее об этом позже.
Переменные препроцессоров не каскадируются
Где бы ни использовались переменные, рано или поздно встает вопрос области видимости. Должна ли эта переменная быть глобальной? Должна ли она ограничиваться своим файлом/модулем? Или блоком?
Поскольку CSS в конце концов оформляет HTML, оказывается, что есть еще один полезный способ ограничивать видимость переменных: на уровне DOM-элемента. Но раз препроцессоры работают не в браузере и никогда не видят разметки, то им это недоступно.
Возьмем сайт, который пытается добавлять класс user-setting-large-text к элементу для пользователей, выбравших увеличенный текст. Когда этот класс задан, переменной $font-size должно присвоиться большее значение:
$font-size: 1em; .user-setting-large-text { $font-size: 1.5em; } body { font-size: $font-size; }Но опять же, как и с блоком медиавыражения раньше, Sass игнорирует это присваивание переменной целиком, так что сделать подобное не получится. Вот вывод:
body { font-size: 1em; }Переменные препроцессоров не наследуются
Хотя формально наследование входит в каскад, я хочу выделить его отдельно, потому что много раз хотел, но не мог воспользоваться этой возможностью.
Возьмем случай, когда вам нужно оформить DOM-элемент в зависимости от того, какие цвета применены к его родителю.
.alert { background-color: lightyellow; } .alert.info { background-color: lightblue; } .alert.error { background-color: orangered; } .alert button { border-color: darken(background-color, 25%); }Это не валидный код Sass (тем более CSS), но вы, наверное, поняли, чего этим кодом пытались добиться.
Последнее объявление пытается применить Sass-овую функцию darken к свойству background-color, которое элемент мог унаследовать от своего родительского элемента .alert. Если к выпадающему сообщению добавили класс info или error (либо цвет фона произвольно изменили скриптом или пользовательскими стилями), кнопке надо уметь подстраиваться под это.
Очевидно, это не заработает в Sass, потому что препроцессоры ничего не знают о структуре DOM, но, надеюсь, уже понятно, почему что-нибудь в таком духе было бы весьма кстати.
Вот один важный случай, который стоит выделить: было бы крайне удобно, если можно было бы применять цветовые функции к унаследованным DOM-свойствам — ради доступности. Например, чтобы сделать текст всегда заведомо читаемым и достаточно контрастным относительно фона. С пользовательскими свойствами и новыми функциями цвета в CSS это вот-вот станет возможным!
Препроцессорные переменные не универсальны
Это достаточно очевидный недостаток препроцессоров, но я упомяну его, так как по-моему он важен. Если вы делаете сайт с PostCSS и вам понадобился сторонний компонент, оформление которого настраивается только через Sass — вам не повезло.
Нельзя (как минимум, непросто) использовать общие переменные препроцессоров для разных инструментов или для сторонних стилей, размещенных на CDN.
«Родные» CSS-переменные будут работать с любым CSS-препроцессором или даже статичным CSS-файлом. В отличие от препроцессорных.
В чем отличие пользовательских свойств
Как вы, наверное, догадались, ни одно из перечисленных ограничений не относится к пользовательским CSS-свойствам. Но, пожалуй, еще важнее причина, почему их не касаются эти ограничения.
Пользовательские CSS-свойства — такие же CSS-свойства, как и обычные, и ведут себя они точно так же (с тем очевидным исключением, что они не применяют никакого оформления к чему-либо).
Как и обычные CSS-свойства, пользовательские свойства динамичны. Их можно менять во время выполнения, их можно обновлять в медиавыражении или при добавлении нового класса в DOM. Их можно задавать инлайново (для какого-то элемента) или в обычном CSS-объявлении с селектором. Их можно обновлять либо перекрывать, пользуясь всеми правилами каскада, либо скриптом. И что, пожалуй, еще важнее, они наследуются, так что когда их применяют к DOM-элементу, они доходят и до его потомков.
Короче говоря, препроцессорные переменные ограничены статической областью видимости и после компиляции сами становятся статичными. Видимость пользовательских свойств привязывается к DOM. Они «живые» и динамические.
Примеры из жизни
Если вам еще не очень понятно, что это за задачи, с которыми пользовательские свойства справляются, а переменные препроцессоров — нет, то вот для вас несколько примеров.
Вообще говоря, я хотел показать просто массу отличных примеров, но чтобы статья не раздулась до неприличия, пришлось ограничиться двумя.
Я выбрал эти примеры, потому что они не чисто теоретические, я действительно сталкивался с такими задачами. Ясно помню, как пытался заставить их работать с препроцессорами, но это было просто невозможно. А с пользовательскими свойствами стало возможным.
Отзывчивые свойства с медиавыражениями
Многие сайты используют переменную «gap» или «gutter», которая определяет зазор по умолчанию между блоками в раскладке, а также отступы по умолчанию для всех разделов страницы. Чаще всего хочется, чтобы этот зазор зависел от размера окна браузера. На больших экранах нужно больше пространства между элементами («больше воздуха»), но на маленьких экранах столько места взять негде, поэтому зазоры должны быть меньше.
Как я уже упоминал, переменные Sass не работают с медиавыражениями, так что код каждого варианта придется писать по отдельности.
Следующий пример определяет переменные $gutterSm, $gutterMd и $gutterLg, а затем объявляет разные правила для каждого варианта:
/* Объявляет три значения зазора, по одному для каждого размера экрана */ $gutterSm: 1em; $gutterMd: 2em; $gutterLg: 3em; /* Базовые стили для маленьких экранов, с $gutterSm. */ .Container { margin: 0 auto; max-width: 60em; padding: $gutterSm; } .Grid { display: flex; margin: -$gutterSm 0 0 -$gutterSm; } .Grid-cell { flex: 1; padding: $gutterSm 0 0 $gutterSm; } /* Переопределят стили для средних экранов, с $gutterMd. */ @media (min-width: 30em) { .Container { padding: $gutterMd; } .Grid { margin: -$gutterMd 0 0 -$gutterMd; } .Grid-cell { padding: $gutterMd 0 0 $gutterMd; } } /* Переопределяем стили для больших экранов, с $gutterLg. */ @media (min-width: 48em) { .Container { padding: $gutterLg; } .Grid { margin: -$gutterLg 0 0 -$gutterLg; } .Grid-cell { padding: $gutterLg 0 0 $gutterLg; } }Чтобы добиться абсолютно того же самого с пользовательскими свойствами, достаточно объявить стили всего однажды. Можно воспользоваться единственным свойством --gutter, а затем при изменениях размеров окна обновлять его значение, и всё само подстроится соответственно.
/* Объявляет, чему равно `--gutter` при каждом размере экрана */ :root { --gutter: 1.5em; } @media (min-width: 30em) { :root { --gutter: 2em; } } @media (min-width: 48em) { :root { --gutter: 3em; } } /* * Стили нужно определять только один раз, так как * пользовательские свойства автоматически обновляются. */ .Container { margin: 0 auto; max-width: 60em; padding: var(--gutter); } .Grid { --gutterNegative: calc(-1 * var(--gutter)); display: flex; margin-left: var(--gutterNegative); margin-top: var(--gutterNegative); } .Grid-cell { flex: 1; margin-left: var(--gutter); margin-top: var(--gutter); }Даже при всей многословности синтаксиса пользовательских свойств объем кода для той же задачи существенно сократился. И здесь мы учитывали лишь три варианта. Чем больше у вас будет вариантов, тем больше кода можно будет сэкономить.
Следующий демо-пример использует этот код для базовой раскладки страницы, автоматически подстраивающей величину зазора под изменения ширины окна. Посмотрите его в действии в браузере, поддерживающем пользовательские свойства!
Смотреть пример на CodePen: в режиме редактора / на всю страницу
Оформление в зависимости от контекста
Оформление в зависимости от контекста (разные стили элемента в зависимости от того, где он окажется в DOM) в CSS — тема жарких споров. С одной стороны, авторитетные CSS-разработчики призывают такого избегать. Но с другой стороны, большинство до сих пор каждый день это делает.
Гарри Робертс недавно поделился своими соображениями по теме в этой статье:
Если вам нужно по-разному украшать интерфейсный компонент в зависимости от того, где он находится, то с вашим подходом к дизайну что-то не так… Надо проектировать вещи так, чтобы им не нужно было знать об окружении, так, чтобы у нас всегда был просто «этот компонент», а не «этот компонент внутри…»
Хоть я и поддерживаю Гарри в этом (и многом другом), я думаю, что такая популярность «кратчайшего» пути решения подобных задач указывает на большую проблему: языку CSS не хватает выразительности, и ни один из существующих «правильных подходов» не устраивает людей до конца.
Следующий пример показывает, как большинство подходит к оформлению по контексту в CSS, используя селектор потомка:
/* Стили обычной кнопки. */ .Button { } /* Стили кнопки, находящейся в «шапке», отличаются. */ .Header .Button { }У этого подхода много проблем (которые я объясняю в статье об архитектуре CSS). Одна из причин считать этот прием «запашком» кода — он нарушает принцип открытости/закрытости: при нем изменяются детали реализации закрытого компонента.
Программные сущности (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для изменения.
Пользовательские свойства меняют наш взгляд на определение компонентов, причем интересным образом. С ними мы впервые сможем писать такие компоненты, которые будет действительно открыты для расширения. Вот пример:
.Button { background: var(--Button-backgroundColor, #eee); border: 1px solid var(--Button-borderColor, #333); color: var(--Button-color, #333); /* ... */ } .Header { --Button-backgroundColor: purple; --Button-borderColor: transparent; --Button-color: white; }Отличие этого примера от предыдущего тонкое, но важное.
С селектором потомка мы объявляем, что кнопки в «шапке» будут выглядеть вот так, и это отличается от того, как определяется сам компонент кнопки. Это какое-то диктаторское объявление (по меткому выражению Гарри), и его трудно отменить, если в каком-то исключительном случае кнопка в «шапке» не должна так выглядеть.
С пользовательскими же свойствами компонент кнопки по-прежнему ничего не знает о контексте и никак не сцеплен с компонентом «шапки». Его объявление всего лишь говорит: «Я буду применять к себе стили на основе этих пользовательских свойств, какими бы они ни были здесь и сейчас». А компонент «шапки» говорит всего лишь: «Я собираюсь задать такие значения свойств; мои потомки сами решат, как их использовать и использовать ли вообще».
Главное отличие в том, что компонент кнопки сам решает, надо ли его расширять, и это легко отменить для какого-нибудь исключения.
Следующий пример показывает оформление по контексту для ссылок и кнопок как в «шапке» сайта, так и в контентной области.
Смотреть пример на CodePen: в режиме редактора / на всю страницу
Исключительные случаи
Чтобы еще лучше показать, насколько проще при таком подходе делать исключения, представьте, что в «шапку» добавили компонент .Promo, а кнопки в компоненте .Promo должны выглядеть не как кнопки в «шапке», а как обычные кнопки.
С селекторами потомков вам пришлось бы написать кучу стилей для кнопок в «шапке», а затем отменить эти стили для кнопок в промоблоке, что и выглядит неаккуратно, и ошибиться с этим легко, а с ростом вложенности оно вообще идет вразнос.
/* Стили обычной кнопки. */ .Button { } /* Стили кнопки, находящейся в «шапке», отличаются. */ .Header .Button { } /* Отмена стилей тех кнопок в «шапке», которые еще и в промоблоке. */ .Header .Promo .Button { }С пользовательскими свойствами мы просто задаем свойствам кнопки какие угодно новые значения, либо сбрасываем их до значений по умолчанию. И независимо от количества исключений стили везде будут переопределяться одним и тем же образом.
.Promo { --Button-backgroundColor: initial; --Button-borderColor: initial; --Button-color: initial; }Полезный опыт из React
Когда я только присматривался к идее оформления по контексту с помощью пользовательских свойств, я был скептиком. Вы уже в курсе, что мне ближе независимые компоненты, которые сами определяют собственные варианты, а не приспосабливаются к произвольным данным, доставшимся в наследство от предка.
Но мое мнение стало меняться, когда я сравнил пользовательские свойства в CSS c props в React.
Эти props из React — тоже динамические переменные с видимостью, привязанной к DOM, и они наследуются, благодаря чему компоненты могут становиться контекстозависимыми. В React родительские компоненты передают данные дочерним, а дочерние уже определяют, какие props они готовы принять и что собираются с ними делать. Эта архитектурная модель широко известна как однонаправленный поток данных.
Даже с учетом того, что пользовательские свойства — новая, неизведанная область, по-моему, успех модели React убедительно доказывает, что можно строить сложные системы на базе наследования свойств. И более того, что переменные с видимостью на уровне DOM — полезный паттерн разработки.
Минимизация побочных эффектов
Все пользовательские свойства CSS по умолчанию наследуемы. В некоторых случаях из-за этого компоненты могут оказаться оформлены не так, как планировалось.
Как я показал в предыдущем разделе, это можно предотвратить, сбросив отдельные свойства, что не даст неизвестным значениям примениться к потомкам элемента.
.MyComponent { --propertyName: initial; }Хоть это еще не вошло в спецификацию, одно время обсуждалось[2] свойство --, которое могло бы сбрасывать все пользовательские свойства. А чтобы выборочно разрешить наследование лишь некоторых свойств, можно отдельно указать для них inherit, благодаря чему они будут и дальше действовать как обычно:
.MyComponent { /* Сбрасывает все пользовательские свойства. */ --: initial; /* Разрешает наследование только следующих польз. свойств */ --someProperty: inherit; --someOtherProperty: inherit; }Управление глобальными именами
Если вы обратили внимание, как я называю свои пользовательские свойства, вы могли заметить, что мои свойства для конкретных компонентов начинаются с имени класса самого компонента, напр. --Button-backgroundColor.
Как и большинство имен в CSS, пользовательские свойства глобальны, и всегда есть риск конфликта имен с другими переменными, с которыми работают ваши коллеги.
Простой способ избежать этой проблемы — договориться о системе именования, например так, как я показал выше.
Для более сложных проектов стоит присмотреться к чему-то вроде CSS-модулей, которые делают все глобальные имена локальными и недавно выказали заинтересованность в поддержке пользовательских свойств.
Итого
Если до этой статьи вы не были знакомы с пользовательскими свойствами CSS, надеюсь, я убедил вас попробовать их. А если вы были в числе скептиков, сомневающихся в их необходимости, надеюсь, ваше мнение переменится.
Пользовательские свойства привнесут в CSS множество новых мощных и динамических средств, наверняка мы пока и не подозреваем, какие еще огромные преимущества откроются в них.
Пользовательские свойства выручают там, где препроцессоры были просто бессильны. Несмотря на это, препроцессорные переменные во многих случаях остаются более простым и изящным выбором. Поэтому я крепко убежден, что в будущем на многих сайтах они будут использоваться вместе. Пользовательские свойства для динамических изменений и переменные препроцессоров для статичных шаблонов.
Я не думаю, что это должен быть выбор «или — или». И противопоставлять их друг другу как конкурентов никому не нужно.
Особые благодарности Эдди Османи и Мэтту Гонту за рецензирование этой статьи, а также Шейну Стивенсу за то, что обратил внимание на баг Chrome и исправил его, чтобы демо-примеры заработали.
Примечания: