Комментарии 65
2. Чтобы все CSS-инструменты строились на основе одного фреймворка — переиспользовали больше кода, меньше конфликтовали
Чтобы был универсальный фреймворк для создания *whatever*
здесь уместно вставить картинку стандарты.jpg
мне кажется, все кто пользовался css-препроцессорами продолжат ими пользоваться.
PostCSS это для староверов, которые не захотели писать less/sass/etc. или им чем-то не нравились эти инструменты, а тут им тот же css, но теперь со вкусом клубники: с автодополнениями, префиксами и причесыванием.
На самом деле PostCSS стал самый популярным CSS-парсером уже, котрый загружается с npm — графики.
Причина в том, что PostCSS используется в куче новых CSS-инструментов, которые не являются препроцессорами. CSS Modules, css-loader в webpack, Stylelint, Autoprefixer, cssnano, uncss, RTLCSS.
не захотели писать less/sass/etc. или им чем-то не нравились эти инструменты, а тут им тот же css
В зависимости от используемых модулей синтаксис pcss
может серьёзно отличаться от «чистых» стилей.
А может и не.
Сасс, лесс, стайлус это готовые наборы обработчиков, изменить или добавить новые сложно.
PostCSS
— платформа для создания своего набора обработчиков. Можно написать их все самостоятельно или выбрать из множества готовых. В статье перечислена лишь малая часть уникальных возможностей, которые появляются благодаря доступу к результату работы парсера.
В общем, сфера применения PostCSS
гораздо шире.
[Перешёл со стайлуса, всем доволен :]
CSS4 не выйдет простите. 4 — это версия определенного css модуля. То есть если вводится новый модуль его первая ревизия получит цифру 1. Если он расширяет возможности предыдущей версии например 3, то получит версию 4.
Таким образом, было принято решение, что для того, чтобы продолжать двигаться вперед, общую спецификацию CSS нужно разбить на множество отдельных спецификаций (модулей), каждый с собственным версионированием. Модули, расширяющие возможности, кото- рые уже присутствовали в CSS 2.1, переводились на уровень 3
Однако модули, посредством которых вводились совершенно новые концепции, начинали свою историю с уровня 1
http://w3.org/TR/css-flexbox-1
© Леа Веру — Секреты CSS. Еще был недавно доклад "Вы не знаете CSS", там много о стандартах было
Картинка про разницу — «в огороде бузина, в Киеве дядька».
Он хранит в себе базу данных Can I Use, пробегается по вашему CSS и находит, что например: «Чувак, ты мне сказал, что ты IЕ хочешь поддерживать, а user selected не поддерживается IE, ты точно уверен, что ты его должен был написать?». Это очень удобная вещь.
Какой в этом смысл? 99% что я специально написал это правило и специально пренебрег его поддержкой в IE — graceful degradation.
rtlcss
Почему это невозможно на sass и зачем там вообще sass, если вопрос решается так:
[dir="rtl"] a { right: 10px; text-align: right; }
Вы пишите обычный код для обычного языка и даже не думаете об арабском:
.menu { left: 10px; text-align: left; }
Потом запускаете RTLCSS и он выдаёт отдельный файл для арабской локали, где будет:
.menu { right: 10px; text-align: right; }
То есть RTLCSS похож на Автопрефиксер — он сам находит нужный свойства в вашем CSS (те, которые специфичны для лево-право) и заменяет их на обратное значение.
В Sass у вас просто нет API для сканирования CSS, только то, что явно указал разработчик в качестве примеси (то есть придётся постоянно думать и легко забыть).
Ну это получается что все равно надо везде пройтись ручками и отключить магию. Нет уж, я лучше примесь сделаю.
Практически все люди в Иране, которым я показывал RTLCSS были без ума от него — они явно отлично разбираются с практикой. Так же WordPress использует только RTLCSS и тоже отлично отзывались о её эффективности на CSSConf в Нью-Йорке.
Я понимаю, что часто хочешь взять что-то старое и не учить, но RTLCSS — «абсолютный хищник» в своей нише. Все кто занимается этим вопросов плотно высоко оценивают его полезность.
Нет, я не боюсь учить новое — если оно мне кажется полезным и качественным.
А почему вам кажется, что нужно будет выключать RTLCSS чаще, чем писать примесь? Может попробуйте на каком-нибудь маленьком тестовом проекте — вы тогда сразу прочувствуете как удобно стало.
Ни вордпресс, ни вк как-то не имеют славу высокой инженерной культуры:)
Потому что я переводил пару интерфейсов на RTL, и там очень далеко не везде нужно было менять left на right и т.д.
Но вы правы, я попробую, когда будет возможность/необходимость.
Плюсик вам в карму за обоснованный евангелизм:)
Я пробовал RTLCSS. Да, проект был небольшой, всего несколько страниц, но мне реально даже не пришлось ничего делать руками. Возможно мне повезло с дизайном, но как бы там ни было, я реально избавился от приличного количества рутины.
Также в добавок к этому, на проекте использовалась каруселька slick у которой есть опция rtl: true
. Благодаря этому всему на том проекте RTL версия далась очень легко. Также впечатление от применения этого плагина усилил тот факт, что клиент опомнился, что ему нужна RTL-версия уже после того, как была готова обычная.
Если я пишу обычный код и даже не думаю об i18n (а это не только RTL), то это плохо кончится в любом случае:) Создавать же отдельные css-файлы для каждой локали — вообще, мне кажется, за гранью.
То есть думать придётся, но на порядок меньше.
Вообще есть проект, который исправления RTLCSS не в отдельный файл переносит, а дописывает таким «патчем», как в вашем первом комментарии.
Но автор RTLCSS (он из Египта и постоянно занимается вопросом RTL) считает, что отдельный файл — проще. Всё равно сборка автоматизирована. Зато максимальная оптимизация по размеру и кол-ву запросов (но, опять же, если вы другого мнения это легко изменить — гибкость PostCSS позволяет).
С переводом локали под готовый, существующий стиль вечные грабли: где-то фразы слишком длинные получаются, где-то слишком короткие. Соответственно, или сокращения прут из всех щелей, или наоборот «дырки» в дизайне появляются. Те же игры достаточно показательны в этом плане.
Понятно, что перевёрстывать всё целиком слишком трудоёмко. Но добавить отдельный файлик с селекторами вида html[lang=ru] <oldselector> {width: ...} — вполне нормальная практика для качественного перевода.
Какой в этом смысл? 99% что я специально написал это правило и специально пренебрег его поддержкой в IE — graceful degradation.
Сейчас лучше всего этот плагин вызывать из Stylelint — там у вас будет спец. комментарий, чтобы явно указать, что вот в этой строчке всё в порядке — вы добавили graceful degradation. С такими явными комментариями и код понятнее (показано что это graceful degradation) и не получиться забыть где-то вставить продумать graceful degradation.
Ну вот, а я сам писал парсер CSS в AST для домашнего минимизатора имен классов. Быть может, перееду на PostCSS.
Мне нравится синтаксис Stylus...
На стороне клиента можно запускать в теории, но готовое решение из коробки пока никто не сделал :(.
Задамъ несколько вопросов:
— Насколько ядро специфично для оффлайн исполнения? Обёрточный клиентский скрипт вобще возможен без переписания ядра?
— Модули клонятся в приложение или можно удаленно затянуть прямо на сторону клиента?
— Генерациия префиксов на стороне клиента в идеале должна зависить от браузера? Нужно будет переписывать модуль (можно на лету фильтровать вашу базу Can i Use или есть возможность прописать настройки модуля)?
Моё самый любимый проект — JSS. Но ещё есть интересный CSJS, у которого есть Babel-плагин, способный запускать PostCSS перед сборкой JS на его стилях.
Так же есть postcss-js, чтобы использовать PostCSS уже в браузере для CSS-in-JS.
У postcss-js уже есть objectifier.js, что для динамически созданых правил может частично помочь, но опять же «удобный CSS-in-JS синтаксис». Думалось о прямом парсинге текста PostCSS, а функции PostCSStoNode нет!
P.S. А так хотелось модулями еще HTML и JS код генерить в дополнение к CSS. Почему каждый проект на Node.js идет самым обходным путем? И делают все на половину или даже меньше. Как по мне то на ентом этапе «постпроцесинг» ничем не оличается от «препроцесинга». Разница чисто концептуальная. PostCSS пошли по той же дороге что и другие. Только SASS шел «спиной вперед» и спотыкался на каждом камне, а PostCSS «лицом» и переступает камни. В конце концов получили тот-же css-файл.
1. Ядро написано для node.js, но специально не привязано к нему. Достаточно собрать его с помощью browserify или webpack и оно будет прекрасно работать в браузере.
2. Модули находятся в npm. Но это не проблема, поскольку легко решается с помощью browserify и webpack. Тот же webpack может грузить модули асинхронно.
3. Да, желательно написать новый Автопрефиксер, так как база данных Can I Use весьма большая, а смысла от неё мало. Но для большинства случаев можно один раз предкомпилировать стили при деплое, а на клиенте просто проставлять значения (не всегда будет работать, но в 99,9% случаев).
Слово «стригифайр» тоже улыбнуло. Странно, что сам автор доклада говорит «не знаю, как перевести» — очевидно же, что это stringifier, т.е. функция, превращающая объект в строку.
// Старческое брюзжание
Ну и самое главное, что со всеми этими плагинами каждый вася придумывает свои способы как написать вот это и так далее, в то время как в sass я точно знаю что это можно сделать вот так и вот так, и вернувшись к проекту через N месяцев я с легкостью пойму что тут нагородили, в отличии от кастомного плагина, который придется идти и изучать.
Давно уже читаю все эти статьи про «sass не нужен, давайте все юзать postcss», но из всех примеров видел пока только одну частично полезную вещь, это конструктор SVG в css (для bg-image) с помощью абстрактного синтаксиса (причем насколько я знаю его потом люди и на sass перетащили без проблем...).
Но вы не правы, что «Sass хватает для всего». Препроцессор не равен всем CSS-инструментам. У нас есть очень много задач. Взять хотя бы тот же uncss (нахождение мёртвого CSS по статичному HTML) — полезно и совершенно нельзя сделать на Sass. Или Автопрефиксер. Или Stylelint. Или RCTLCSS.
Что мешает юзать PostCSS вместе с Sass, вместо того чтобы его хоронить каждый месяц? Я прекрасно понимаю что есть множество крутых плагинов, но полностью отказываться от sass, заменяя его зоопарком из плагинов (некоторые примеры выше прям вообще жуткие в этом плане) нет желания.
Если верить цифрам в табличке о производительности, то ничто не мешает выхлоп sass обрабатывать postcss-ом, который работает на два порядка быстрее (не считая libsass, но мы же в приличном месте).
Непонятно, правда, сколько и каких postcss-плагинов участвовало в том тесте…
Для LESS есть отдельное расширение файлов — .less
Мой PhpStrom знает его синтаксис и ни на что не ругается.
А если я в обычных CSS файлах начну писать какие-то новые, нестандартные селекторы — IDE мне пальцем у виска начнет крутить. Можно конечно отключить все это, но зачем?
Мне посоветовали использовать другое расширение (скажем, *.sss) и добавить его в список расширений для типа файлов LESS. Но я не пробовал.
Для Stylelint есть подсветка ошибок для Atom и Sublime.
Если вы используете препроцессор PreCSS (который на основе PostCSS-плагинов), то ставьте расширение .pcss — подсветка есть для Atom, Sublime, IDE от JetBrains.
RTLCSS — нужен очень немногим, если брать широкую аудиторию обычных разработчиков. Да и его можно так же просто прикрутить.
Если я использую препроцессор, то зачем мне его менять с моего текущего? Все равно 99% функционала одинаковые. Даже различия между LESS и SASS не все разработчики могут назвать (кроме синтаксиса).
Я это к тому, что между PostCSS и препроцессорами нет существенной разницы. Либо ее никто не смог до сих пор внятно объяснить: во всех подобных статьях возникает куча вопросов «А зачем?».
Например, Webpack сразу потестил Grunt и Gulp именно за счет нововведений вроде поддержки импорта, webpack-dev-server и прочих плюшек. В остальном же он делает все то же самое.
PostCSS же в данном случае просто делает все то же самое и не дает ничего нового.
Исключительно мое мнение. Поклонники PostCSS — не воспринимайте слишком близко к сердцу :)
Но то что вы сравниваете PostCSS с Sass — совсем неправильно. PostCSS — фреймворк для создания любых CSS-инструментов. Препроцессор — только одна из множества этих инструментов.
Вы полностью правы, если вы уже используете препроцессор, который не построен на PostCSS — то вам не надо переходить на препроцессор PreCSS на базе PostCSS. Мы об этом как раз и говорим (это запись выступления годичной давности).
Но если вы начинаете новый проект и уже используете кучу инструментов на базе PostCSS? Тут у PreCSS появляется главный смысл — чтобы все инструменты были построены на одной фреймворке (PostCSS). В итоге у вас и быстрее сборка (PostCSS один раз парсит и все инструменты уже работают с готовым AST). Между инструментами гарантировано нет конфликтов. Унификация — это всегда круто.
Ну всё, довод про скорость меня убедил. Завтра же попробую это вписать в свою систему сборки.
PostCSS — это фреймворк для разработки CSS-инструментов.
Вот у вас есть крутая идея минификатора CSS. Или вы хотите написать новые препроцессор. Или вы увидели крутой черновик спецификации и хотите написать полифил. Для всего этого вам нужен парсер, генератор карт-кода, инструменты разработки, обвязка для Grunt, Gulp, webpack.
PostCSS, как раз даёт всё это — парсер, генератор карт кода, инструменты разработчика, обвязки для сборщиков.
Но когда несколько инструментов начинают использовать один парсер PostCSS, получается огромный выигрыш от унификации:
Сейчас у вас Sass парсит исходник, генерирует CSS. Минификатор снова парсит строку. Прасинг — самый долгий процесс в работе CSS-инструментов. Если все инструменты будут использовать один парсер, то зачем нам парсить на каждом шаге — парсим один раз в начале, а между плагинами передаём отпарсенное дерево.
Кроме того, унификация даёт ещё пару плюсов. Все инструменты становятся совместимы между собой (линтер не будет падать от синтаксиса «CSS4» вашего полифила). Инструмент созданный для одного проекта (парсер битого CSS или вывод ошибки в браузер) становится доступен всем инструментам.
Собственно в этом и смысл PostCSS. Это платформа для создания новых CSS-инструментов. Чем больше у вас инструментов основанных на PostCSS, тем больше плюсов вы получаете от унификации.
Вот у вас есть крутая идея минификатора CSS.
Есть такая идея. Прошу меня извинить за небольшой офтоп…
Вот честно говоря, сомнительно, что PostCSS «не приседая со штангой» сможет построить правильную синтаксическую модель CSS. Дело в том, что стандарт CSS 2/3/4 — это уже настолько сложный и запутанный документ, что обычными регулярками его не распарсишь.
Чего только стоят синтаксис селекторов, квалификаторов, выражений медиа-запросов (@media), и формат условных запросов (@conditional),… если внимательно почитать документацию.
Ну вот для примера.
Знаете ли вы, что вот эта конструкция является валидным именем класса:
.data\\\{5\} {… }
А как вам такой селектор по атрибуту:
[my|src^="/icon/"]
Или вот еще простенький квалификатор:
.colorized[ href
]:NOT(
.blue.dark.orange
)
А может быть такой селектор:
*|P * .test + P > span ~ em {...}
Или вот еще, финт со строками:
a::before
{
content: 'Этот текст слишком длинный\
так что я пожалуй перенесу \0000A \U+0003F #&567; его на следующую строку'
}
Ах, да, вот еще можно так:
.class { background-image: url(/my_url:;-.png) }
А еще добавьте к этому всему esape-последовательности, unicode-символы, инструкцию charset (которая прикажет нам сменить кодировку файла на лету), и т.п. и т.п. И все это парсер CSS должен поддерживать.
Кому интересно, вот несколько ссылок про CSS стандарт.
http://www.w3.org/TR/css-syntax-3/
http://www.w3.org/TR/css3-selectors/
http://www.w3.org/TR/css3-webfonts/
http://www.w3.org/TR/css-fonts-3/
http://www.w3.org/TR/css3-animations/
http://www.w3.org/TR/css3-values/
http://www.w3.org/TR/css3-color/
http://www.w3.org/TR/css3-namespace/
https://www.w3.org/TR/css3-images/
http://www.w3.org/TR/css3-mediaqueries/
http://www.w3.org/TR/css3-conditional/
http://www.w3.org/TR/css-ui-3/
http://www.w3.org/TR/css-counter-styles-3/
http://www.w3.org/TR/css-flexbox-1/
http://www.w3.org/TR/css-masking-1/
http://www.w3.org/TR/css-shapes-1/
http://www.w3.org/TR/css-writing-modes-3/
И это только 3-й.
Может быть поэтому PostCSS и уделывает других за счет того, что слишком упрощенно подходит к анализу файлов?
Кроме того тех проблем, что ты указал (куча спецификаций) есть ещё более большая — а как делать полифилы или расширения CSS типа CSS Modules?
Поэтому у PostCSS специально чуть другая философия. На самом деле парсинг состоит из 2 частей — разбор «грамматики» и разбор «смысла». Вот если мы парсим «Вилкой удобно есть суп». Когда мы «парсим» грамматику, мы только определяем, где подлежащие, сказуемое и т. д. Но мы не пытаемся понять конкретный смысл фразы. Потом мы уже по грамматике можем отпарсить смысл, взяв данные по отношению вилки, супа и т. п. (тут бы мы заметили ошибку смысла, так как вилкой не удобно есть суп).
Тоже самое и в PostCSS. Она парсит только структуру CSS, но не смысл конкретных выражений. Конкретно мы используем эту спецификацию https://www.w3.org/TR/css-syntax-3/
Если разработчикам плагинов нужен смысл каких-то блоков — они могут использовать специальные допарсеры — postcss-selector-parser, postcss-value-parser и т. п.
Есть и другой подход — например, csstree парсит всё целиком.
Но, как я уже писал, на полном парсере (которые будет всё проверять) не написать огромное количество очень нужных CSS-инструментов. Так что такой подход просто не подходит для целей PostCSS.
Может быть поэтому PostCSS и уделывает других за счет того, что слишком упрощенно подходит к анализу файлов?
Не совсем. Многие парсеры в нашем бенчмарке парсят тоже очень приближенно. С другой стороны, csstree парсит всё, как вы хотите, но даже быстрее PostCSS.
На самом деле, практически весь вопрос скорости парсинга — это токенайзер. Оптимизировать имеет смысл только его. Если парсить всё, то токенов, конечно, будет больше — но не принципиально. Все эти проверки и разбор спецификаций в основном будет происходить уже после токеном. А по моему опыту, что ты будешь делать после токенов уже не особо важно с отношении скорости.
──────────────────
У PostCSS куцый AST, и то, что плагинам приходится «парсить» декларации вручную — имхо, большое зло. В кавычках слово «парсить» не случайно, разве можно назвать парсингом тупую регулярку? Регулярка вида /\b(\w+)\(/ — это в лучшем случае, в основном в плагинах юзают indexOf. Все это выливается в то, что практически все плагины, которые «расширяют» синтаксис деклараций или вводят функции, ломаются на подобном css-коде (или портят его)
.cssclass1 { content: "-=)some(=-" } .cssclass1 { content: "MyOwnSuperDuperFunction(param)" }
Я понимаю, что вероятность подобного кода исчезающе мала, но я не доверяю решениям которые, не то что не имеют защиты от дурака, но полагаются на строго определенные юзкейсы.
По факту, никто не хочет писать полноценный парсинг деклараций, тем более, что это просто дико писать полноценный корректный парсер для каждого плагина, — зачем, тогда, спрашивается, вообще, нам готовый AST?
Я бы предпочел иметь в плагинах более детальный AST, а это значит, что нужен «синтаксис будущего», по крайней мере некий более определенный синтаксис.
Абсолютно согласен. Являясь любителем поизобретать велосипеды как-то задумал написать парсер CSS с целью дальнейшей оптимизации. И столкнулся как раз тем же. Жуткий синтаксический бардак. Токенизатор должен слегка разбираться в синтаксисе, чтоб работать однозначно. Очень много ненужного. Такое впечатление, что это плод коллективного творчества. К имеющимся конструкциям прикручивают и прикручивают уродства. Т.е. изначальная идея была проста и практична, но то-что пытаются из CSS выжать сейчас — это даже эпичнее, чем апгрейд C в C++.
Со стороны вообще вся эта ситуация выглядит довольно весело. Значит вчера Вася пользовался Sass, Gulp, в котором прописал задачи автопрефиксов, минимизации, линтинг и так далее… А сегодня Вася делает все то же самое (или стремится так делать), но с помощью PostCSS, который носит гордое название постпроцессора и красивые цифры в замерах производительности на картинках
PostCSS. Будущее после Sass и Less