Нужны ли CSS-препроцессоры в 2018 году, или насколько мы близки к ванильному CSS

Среди разработчиков сейчас есть тенденция отказа от препроцессоров в пользу ванильного CSS. Давайте разберёмся, готова ли веб-платформа полностью заменить препроцессоры.

Начнём с того, что классические препроцессоры вроде Sass/Less/Stylus свой век почти отжили — им на смену пришли современные возможности CSS, а также PostCSS с большой экосистемой плагинов. PostCSS по сути тоже препроцессор, только модульный — это главная причина его популярности и нужности. Подключаете и используете только нужные плагины, а если нужно что-то нестандартное, всегда можно написать свой плагин.

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

В идеале хотелось бы избавиться от PostCSS и оставить только ванильный CSS (#usetheplatform). Как дела с ключевыми возможностями препроцессоров в веб-платформе?

Математические выражения. Поддерживаются нативно в виде функции calc() в CSS. Более того, calc() поддерживается подавляющим большинством браузеров — проблемы есть только в IE9-, Android Browser 4.3- и Opera Mini. Есть плагин postcss-calc, заранее вычисляющий на этапе сборки всё, что можно.

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

:root {
  --base-font-size: 16px;
}

@media (min-width: 1280px) {
  :root {
    --base-font-size: 18px;
  }
}

Кастомные свойства не поддерживаются в IE 11- и в большинстве мобильных браузеров. Базовая функциональность кастомных свойств реализуется плагином postcss-custom-properties — он на этапе сборки вычисляет все значения переменных и подставляет их в места использования, на выходе получается обычный CSS-файл с захардкоженными значениями. Динамическое переопределение значений переменных в медиавыражениях плагином не поддерживается.

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

:root {
  --base-font-size: 16px;

  @media (min-width: 1280px) {
    --base-font-size: 18px;
  }
}

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

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

.popup {
  --heading-style: {
    font-weight: bold;
    text-transform: uppercase;
  }
}

.popup__title {
  @apply(--heading-style);
}

На первый взгляд круто, но в таком решении есть проблемы из-за смешения обычных переменных, используемых через var(), и блоков правил, используемых через @apply() — Таб Аткинс подробно описал эти проблемы и сразу же предложил новое решение на основе Shadow DOM — псевдоэлемент ::part(). Из статьи с описанием проблем мне стало ясно, что у Таба изначально было немного другое видение предназначения примесей.

Таб заметил, что кастомные свойства не дают достаточно гибкости для стилизации веб-компонентов. В качестве примера рассмотрим попап — изолированный компонент, к внутренностям которого доступ мы не имеем. Кастомные свойства позволяют настроить внешний вид попапа, например задать цвет его подложки или размер заголовка. Ограничение в том, что внешний пользователь компонента не может доопределить или переопределить стили его частей — например, того же заголовка. Именно эту задачу Таб решил, предложив @apply, и, к счастью, пришёл к лучшему решению с ::part().

Вроде здорово, но есть проблема. Основная задача, которую решают примеси — не до- или переопределение стилей, а абстракция. Есть замечательная статья, объясняющая, что CSS — неэффективный язык, потому что в нём нет средств абстракции и комбинирования. Примеси в первую очередь полезны для абстрагирования стилей и комбинирования этих абстракций. Только примеси позволяют добиться настоящего разделения разметки и стилей:

Разделение разметки и стилей с помощью примесей

В общем, так как Таба Аткинса унесло в другую степь, перспектива появления примесей в CSS пока что туманна.

Итого

Из трёх ключевых возможностей (переменные, вложенность, примеси) в CSS реализована только одна — переменные, и то поддержка браузерами пока не позволяет их использовать.

В простых проектах можно начать использовать только нативные возможности CSS с PostCSS-плагинами, выступающими в роли полифилов на этапе сборки. Такой подход я попробовал на одном из проектов. Нужно было сверстать небольшой лендинг. Все стили я написал в одном файле с использованием CSS-переменных, причём на время разработки даже не пришлось настраивать никакую сборку — было достаточно подключить в разметке исходный файл со стилями, Хром нативно поддерживает CSS-переменные. Сборка потребовалась только для вычисления переменных, простановки вендорных префиксов и минификации — это заняло всего 17 строчек кода.

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


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

Share
Send
Pin
6 comments
Alexander

Боялся увидеть тут статью с посылом “препроцессоры – старый отстой, не используйте их, если вы не динозавр” и рад, что не увидел.
Это вызвало бы чувство вины, что я делаю всё не так.

В препроцессорах мне дико удобно писать бэмоподобные селекторы через вложенность – вроде
.block {
&__element {}
}

И пока этого такой возможности не будет в CSS, использовать их будет мучительно больно.

InoY

Согласен с коментатором выше по поводу вложенности.
Переменные поддерживаются всеми последними версиями современных мобильных браузеров: safari/chrome/firefox/samsung browser/android browser. Конечно, есть такие недоразумения как мобильная Opera и, прости господи, UC Browser, но ими пользуются меньше процента юзеров.
Так, что по-моему переменные можно смело юзать.

KowkogaB

Чет статья ни о чем. Сначала автор резюмирует, что препроцессоры не нужны, а потом рассказывает, как с помощью PostCSS реализовывать фичи препроцессоров, устанавливая дополнительные плагины. Так может проще препроцессоры использовать? “Вложенность селекторов, на мой взгляд, не нужна, потому что она поощряет увеличение специфичности и затрудняет чтение кода.” С этого предложения просто бомбануло, и дальше не стал читать. В моей практике почему-то вложенность селекторов наоборот делает стили удобными, читаемыми и логичными. Наверное, автор просто из тех, кто не знает о конкатенации классов, и после таких потом приходится перебивать десятиуровневые селекторы.
В общем, когда будет нормальная поддержка браузерами фишек препроцессоров, тогда можно отказываться от препроцессоров, а пока SASS тащит.

Андрей Романов

KowkogaB, PostCSS — тоже препроцессор, просто современный и модульный.

«Так может проще классические препроцессоры использовать?» — нет, потому что когда понадобится функциональность, которой нет в Sass, вы ничего не сможете сделать, а в случае с PostCSS всегда можно написать плагин.

«В моей практике почему-то вложенность селекторов наоборот делает стили удобными, читаемыми и логичными» — лично я верстаю по БЭМу и мне практически не приходится писать составные селекторы. С составными селекторами начинаются проблемы со специфичностью. Я бы использовал вложенность только для медиавыражений, псевдоклассов/псевдоэлементов и для БЭМ-нотации .block { &__elem {} }.

arias2030

Использовать ванильный css? Не раньше чем:
1) умрут вендорные префиксы
2) из синтаксиса выкинут никому не нужный мусор, вроде символов : ; { }
3) будет вложенность стилей. Хотябы для банально удобной записи бэм селекторов.

После лаконичного stylus обычный css писать не прет. Точно так же не прет писать less, sass, scss ( препроцессоры-да, лаконичность – не, не слышали).

Но как же postcss??? А никак. Он работает с уже сформированными препроцесором стилями. Ему абсолютно по барабану, ты сам написал css, или он сформирован автоматически.

Поэтому пишу на stylus использую плагины postcss, а на тенденцию отказа от всего и писать на всём ванильном могу ответить – пишите сайты на ассемблере, это будет самая ванильная ванильность и успокойтесь уже.

Maksym Bondarchuk

Отказался от PostCSS в пользу SCSS. Там где в SCSS всё из коробки, в PostCSS нужно подключить 2 десятка зависимостей. Да и function+mixin в SASS отлично работают и почти во всём заменяют модули. К тому же всегда можно использовать PCSS поверх SASS, уменьшая таким образом количество плагинов и зависимостей (nesting, variables etc...)

Данил

А что насчет styled-components и прочих CSS-in-JS’ин?
Ванилька их тоже убьет или они вообще не конкуренты?

Your comment
won’t be published

HTML will not work

Ctrl + Enter
Popular