Нативные переменные в CSS. Уже пора…

  • Tutorial

Всем привет, тема переменных в CSS давно ходит по интернету, однако не все знают о том, что это такое, да и сама технология не так давно вышла в релиз. И хоть использовать её во многих случаях рановато, уже пора понимать что она из себя представляет и как ею пользоваться. Давайте попробуем разобраться с технологией вместе. Обращу ваше внимание, что эта статья для тех, кто не знает о CSS переменных (кастомных свойствах) или только слышал о них. Если вы знакомы и умеете работать с данной фичей, то вам данная статья будет не интересна.

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

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

:root {
    --body-background: #ccc;
}

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

Как видно из листинга выше, переменные объявляются двумя дефисами перед именем:
--variable-name

Чтобы использовать переменную, необходимо воспользоваться функцией var. Она имеет 2 параметра. Это, естественно, имя переменной, а вторым необязательным параметром идёт значение свойства, которое необходимо использовать в случае отсутствия переменной.

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

.title {
  --wrapper-width: 50%;
  width: var(--wrapper-width);
}

@media (max-width: 320px) {
  --wrapper-width: 100%;
}

Всё! Этого достаточно, чтобы свойство width изменило свое значение!

Если CSS способен отслеживать изменения своих переменных, это значит, что с этим можно взаимодействовать различными способами.

Что насчёт JavaScript?


Управляя аттрибутом style, можно изменить стиль, прибегая к минимальным затратам усилий. Приведу грубый пример на React.

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

changeColor() {
  this.setState({
    style: {'--background': 'green'}
  });
}
<div className="title" style={this.state.style} onClick={this.changeColor.bind(this)}>Title</div>

Теперь по клику на элемент с классом title будет меняться цвет фона у элемента. Круто? Ещё бы! Не нужно добавлять новый класс, переопределять свойство или делать другие действия, способствующие изменению фонового цвета у элемента.

Ремарка
Если кто-то не знаком с React или кому-то просто непонятно, что произошло. Мы просто средствами JavaScript изменили аттрибут style у элемента, изменив значение переменной
--background

Используя переменные, изменять css извне стало проще, методов использования можно придумать массу, а мы пойдем дальше.

Области видимости


Нужно сказать пару слов об области видимости CSS переменных, здесь всё просто. Объявленная переменная доступна всем селекторам дочерних элементов данного селектора. Т.е. в листинге ниже использовать переменную --b в тэге html будет нельзя. А вот переменная --a в body и всех дочерних элементах будет работать без проблем (если её конечно не переопределят где-то ниже).

html {
  --a: #ccc;
}
body {
  --b: #a3a3a3;
}

(я знаю, что цвета в примерах скучные, но я плохо помню цвета по hex-коду :))

Переменные и calc


Как и любое числовое значение свойства, вы можете использовать переменную в функции calc.

.title {
  --title-width: 300px;
  width: calc(var(--title-width) + 150px);
}

Круто! Особенно если учесть что переменную --title-width, можно менять как внутри CSS, так и извне.

Заметьте, что величину мы обязаны положить в переменную. Дописать px, %, rem и т.д. к вызванной переменной у нас не получится. Однако ничто не мешает нам умножить с помощью функции calc значение на единицу в необходимой нам величине.

.title {
  --title-width: 300;
  /* так не сработает */
  width: var(--title-width)px;
  /* так сработает */
  width: calc(var(--title-width) * 1px);
}

В заключение


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

Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 34

  • UFO just landed and posted this here
      0
      Такое правило спецификации. Нужно же как-то отделить кастомное свойство от остальных.
        0

        Из-за такого синтаксиса переменных печатать их неудобно, а код выглядит неаккуратно.

          +1
          Да, интересно, чем им $var_name как в SCSS не угодил
            +2

            Может чтоб не мешать CSS с SCSS?

        0

        Помните браузерные префиксы? Вроде -webkit-linear-gradient? Так тут то же самое, только с пустым именем префикса, как -webkit- без слова «webkit»:
        --имя-переменной
         ↑
        тут ничего


        Обсуждались разные варианты: Начало с доллара «$» слишком похоже на Перл и конфликтует с препроцессорами. «var-» плохо выглядит с функцией var(): «var(var-имя-переменной)».


        Так что, это самый понятный и не конфликтующий с другими свойствами вариант.

          +1

          Автор спецификации объяснил это тем, что переменные это то, что внес сам разработчик, и типо они не от браузера или спецификации. Когда браузер вносит свое свойство, которое еще типо не доработано или еще по каким то причинам, то начинает его с -webkit-, а в случае с переменные это, то что внес разраб и поэтому нету имени, между — -.
          Я когда читал это, не думал, что придется кому-то объяснять. Поэтому, не обратил на это должного внимания)

          +3
          У меня в голове ну укладывается, почему такая мощная организация как Microsoft, не может сделать нормальный современный браузер?.. Тем более что многие стандарты по CSS разрабатывали их сотрудники.
            0
            У меня в голове не укладывается как вообще кому-то пришло в голову имя переменной начинать с дефисов, ведь никакой необходимости отделять (как выше комментировано) их нету, наоборот весь стиль это набор переменных, на месте Microsoft из принципа такое говно не пропустил.
              0
              никакой необходимости отделять (как выше комментировано) их нету

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

                +1
                Я про этот комментарий.
                Нет необходимости визуально отличать переменные от свойств, свойства это просто предефайненные переменные.
                  0
                  да даже так — var-ссссс-ссссс (допустим «var-» обязательно), выглядит более уместно:

                  .title {
                    var-title-width: 300px;
                    width: calc(var-title-width + 150px);
                  }
                  

                    0
                    Я не пониманию в чём проблема понять, что для объявления и использования переменной, необходимо писать -- перед именем. Если вы этого делать не будете, то браузер будет парсить имя переменной как неопределенное свойство CSS.

                    Авторы технологии приняли решение о таком синтаксисе, и с этим ничего не поделаешь.
                    0

                    Хорошо, если свойства вам хочется назвать "предефайненными переменными", то это нововведение правильней было бы назвать "юзер-дефайнед константами". В языке С, например, константы принято именовать заглавными буквами (хотя это не строгое требование компилятора, а просто выработанный многолетним опытом программистов code style). Так просто кодить реально удобнее, когда мух от котлет визуально легко отличить, особенно когда у нас килограмм мух в центнере котлет размешан.


                    P.S. Ну и для совместимостями с будущими версиями — если вдруг у какого-то элемента появится новое свойство в следующей версии HTML/CSS — у программистов, дизайнеров и верстальщиков не будет головной боли по поводу "а не назвали ли мы так наши переменные в нашем коде, и не нужно ли теперь в срочном порядке их везде переименовывать".

                0
                Edge вполне себе современный браузер. Пользуюсь им на корпоративном лэптопе, даже удивляюсь. IE находится в замороженном состоянии, как мне видится. Если и будет обновляться, то раз в n лет (как обычно).
                +3
                Если послать нахрен ишака, то вполне можно применять.
                  +1
                  Даже с ишаком можно применять, если использовать, например, cssnext.
                    0
                    cssnext просто скомпилирует результат, с ним нельзя будет работать из js, например. Кастомные свойства это не просто про переменные препроцессоров.
                  0
                  А где можно увидеть реальное применение этих переменных, так чтобы это выглядело удобным? Я пока что для себя не могу придумать. И есть ли полифилы?
                  • UFO just landed and posted this here
                      0
                      При разработке вопросов не возникает, но эту нишу закрывают сейчас препроцессоры, которые все равно удобнее использовать чем нативный CSS. Наверное вопрос нужно немного перефразировать. Какое применение переменных при работе сайта (не разработке)?
                        0
                        Очень важное отличие переменных препроцессоров и чистого CSS, что в препроцессорах переменные неизменны, а в CSS могут меняться внутри селекторов. К тому же, удобно использовать их в media queries

                        Вот небольшая статья об этом
                    0
                    Переменные давно уже существуют в препроцесорах, для себя так и не нашёл их применения, поиск и замена по файлам быстрее и проще.
                      0
                      Это лучшее решение, которое я только видел!
                        0
                        Это же сарказм, да?
                          +1
                          Ну как можно )) это ж так увлекательно, берешь какое-нибудь магическое 12 и ищешь, и ищешь! А потом приходит такооое удовлетворение от качественно выполненной работы, сам собой гордиться начинаешь!
                        0
                        Я тоже так подумал поначалу, но это принципиальная ошибка.
                        Нативные переменные намного круче и гибче, потому что их можно менять налету, а препроцессорные существуют только на этапе компиляции.
                        +1
                        > Приведу грубый пример на React

                        А без реакта?
                          0

                          Реакт — это новый jQuery. Без него никак! ;)

                          0
                          Ну тут история как с IE6. Чтобы в продакшене верстать, то надо будет добавлять все костыли пока оно не умрёт. Сейчас разве что жать когда IE умрёт окончательно…
                            0

                            Хм… Довольно неплохая штучка))

                              0
                              Надо было и про полифил написать и насколько он накрывает базовый функционал.
                                0
                                Наверное можно было бы пару слов сказать о них (если получится уместить материал в «пару слов»), но это одна из сотни возможностей, сделать стили гибче и лучше. Не каждый будет внедрять post-css в свой огромный проект, или изощряться с транспайлерами, дабы иметь наконец возможность писать эти переменные. Во вторых, я не могу быть уверен, что технологию можно заполифилить целиком. И в третьих, статья преследует цель познакомить читателя с технологией, всё.
                                +1

                                боюсь предположить, что будут означать три минуса перед словом в следующей спецификации...

                                Only users with full accounts can post comments. Log in, please.