Большинство считает CSS чем-то простым и не заслуживающим внимания. Но за мнимой простотой кроется большая сложность и огромный пласт проблем, не имеющих пока решения. Современный CSS с его объёмами, новыми фичами, разной поддержкой и багами браузеров, уже почти не поддается анализу человеком. Для этого появляются программы, которые разбирают CSS на атомы, анализируют и помогают сделать его лучше. Как к этому прийти, где мы сейчас и что ещё предстоит сделать.
6. Но сейчас больше
страдают разработчики
5
Сложно обрабатывать CSS,
т.к. очень много нюансов
«создатели»
7. Но сейчас больше
страдают разработчики
5
Сложно обрабатывать CSS,
т.к. очень много нюансов
«создатели»
Баги и непредсказуемость
результатов
«пользователи»
8. Рассказываю, потому что подгорает :)
• CSSO (мейнтейнер) – минификатор CSS
• CSSTree (автор) – набор инструментов по работе
с CSS, включающий parser, walker, lexer,
generator и т.д.
6
11. Сложности
• Большое количество директив, свойств, функций и т.д.
• Исключения и особые правила
• Белые пятна в спецификациях
• CSS меняется
• Разная поддержка браузерами
• Баги браузеров
• Хаки
9
12. Проблемы
• К CSS меньше внимания чем к другим веб-технологиям
• Низкий уровень знания CSS
• Препроцессоры
• FCSS (Fantasy CSS из доклада Вадима Макеева)
• Много CSS кода в проектах (мегабайты)
• Недооценивание масштаба проблем (я оптимист!)
10
13. • Директивы (at-rule) – 40
• Медиа фичи (media feature) – 69
• Псевдо-классы – 125
• Псевдо-элементы – 146
• Свойства – 1150
• Функции – 69
• Единицы измерения (unit) – 30
11
• Цифры включают легаси и
вендорные имена
• Собрано для словарей CSSTree
в рамках проекта real-web-css
16. А вы задумывались ...
• Как машины видят CSS?
• Как понимают его значение?
• Как понимают что правильно, а что нет?
• Что нужно, чтобы объяснить им как должно быть?
• ...
14
32. Так работают ...
• Линтеры (проверяют ошибки)
• Минификаторы
• Подсказки в IDE/редакторах
• Программы форматирования кода
• Пре- и пост-процессоры
• Autoprefixer и т.д.
23
36. Какие сложности это вызывает
• Нет совместимости между инструментами с разными
парсерами
• Разработчики парсеров решают одни и те же проблемы
• Сложно с именованием типов узлов и их свойств
• Открытые вопросы как представлять разные части CSS
• Конфликт интересов в формате для разных задач
• Не понятно как правильно
27
37. Спецификации CSS
не рассматривают формат AST,
так как они нацелены на браузеры
28
38. Что получается у меня:
29
Формат AST в CSSTree
По прежнему есть открытые вопросы :(
44. Детальность
32
Меньше Больше
• Больше типов узлов
• Больше памяти на хранение узлов
• Больше времени на обход дерева
• Необходим дополнительный разбор
• Так как "доразбор" на стороне
пользователя: больше зависимостей
и шансов сломаться
45. Пример: перевод px в rem
33
// !singlequotes|!doublequotes|!url()|pixelunit
var pxRegex = /"[^"]+"|'[^']+'|url([^)]+)|(d*.?d+)px/ig;
ast.walkDecls(function (decl, i) {
...
decl.value = decl.value.replace(pxRegex, function (m, $1) {
// 16px -> 1rem
});
});
postcss-pxtorem (PostCSS плагин)
(недетальное AST)
46. Та же задача с детальным AST
34
csstree.walk(ast, function (node) {
...
if (node.type === 'Dimension' && node.unit === 'px') {
// ... вычисление нового значения (newValue)
node.value = newValue;
node.unit = 'rem';
}
});
(как мог бы выглядеть плагин на CSSTree)
48. Пример: подсчет specificity
36
...
var A = 0, B = 0, C = 0;
simpleSelector.children.each(function walk(node) {
switch (node.type) {
case 'SelectorList':
case 'Selector':
node.children.each(walk); break;
case 'IdSelector':
A++; break;
case 'ClassSelector':
case 'AttributeSelector':
B++; break;
...
модуль подсчета
specificity в CSSO
(57 SLOC)
(детальное AST)
49. Детальность AST
• Нужный уровень детальности зависит от задачи
(например, если обрабатываются только селекторы,
не нужно разбирать значения деклараций)
• Уровень детализации зависит от парсера
• В некоторых парсерах можно управлять
уровнем детализации
37
50. Несколько примеров
• PostCSS
Не разбирает (оставляет строкой): прелюдии у директив и правил
(selector list), значения деклараций. Детализация не настраивается
• CSSTree
Не разбирает значения custom properties, но можно включить
настройкой парсера. Можно отключить разбор прелюдий и значений
деклараций
• Gonzales PE
Самой большой уровень детализации. Детализация не настраивается
38
56. 44
#31 + 2 {
content: "hello
world";
background: url(p(4).jpg);
}
Экранирование
drafts.csswg.org/cssom/#the-css.escape()-method
В идентификаторах можно
использовать любые
символы, если экранировать;
в браузерах есть метод для
этого – CSS.escape()
CSS.escape('1 + 2') === '31 + 2'
57. 45
#31 + 2 {
content: "hello
world";
background: url(p(4).jpg);
}
Экранирование
www.w3.org/TR/CSS22/grammar.html#grammar
Можно экранировать
перевод строки в строках,
как в JavaScript
58. 46
#31 +2 {
content: "hello
world";
background: url(p(4).jpg);
}
Экранирование
www.w3.org/TR/CSS22/grammar.html#grammar
Можно экранировать
специальные символы
в url()
63. 51
@supports (background: top calc(25% + 2px) !important) {
…
}
@supports
С точки зрения спецификаций разрешается все,
что можно в декларации, даже !important
www.w3.org/TR/css3-conditional/#at-supports
64. CSS Syntax Module Level 3
Когда возникает ошибка в CSS, парсер постепенно
восстанавливается, выкидывая минимальное количество
контента перед возвращением к разбору в обычном режиме.
Это связано с тем, что ошибки не всегда являются ошибками –
новый синтаксис выглядит как ошибка для старых парсеров, и
это полезно для добавления нового синтаксиса в язык ...
52
§ 2.2. Error Handling
65. Парсеры CSS толерантные к ошибкам
• CSSTree – толерантный к ошибкам согласно
спецификации
• PostCSS – толерантен к ошибкам, если используется
postcss-safe-parser вместо стандартного парсера.
Соответствие спецификации не известно
• Это все варианты, что я знаю...
53
* парсеры написанные на JavaScript
67. Ключевое
• Нет общего формата AST для CSS
• Уровень детализации AST может быть разный
• Детальное AST может требовать больше ресурсов,
но удобнее для анализа и трансформации
• Парсинг CSS в AST сложная задача, много нюансов
• CSS парсер должен быть толерантным к ошибкам
55
68. Формат AST и его свойства,
определяют что и как
машины могут делать с CSS
56
73. Сложности: декларация
61
@supports (display: flex) {
.foo {
font-family: "Open Sans";
}
}
@font-face {
font-family: "Open Sans";
}
В CSSTree это все декларации
(тип узла Declaration):
• Декларации внутри @supports
обычно обходить не нужно, их
приходится игнорировать (а если
нужны?)
• Внутри @font-face на самом деле не
декларация, а дескриптор
(decscriptor); для них, например,
нельзя применять !important (будет
считать ошибкой и браузер
проигнорирует дескриптор)
75. Сложности: селекторы
63
@page :first {
...
}
@keyframes name {
from { ... }
25%, 75% { ... }
to { ... }
}
.foo {
...
}
В CSSTree это все селекторы
(тип узла SelectorList):
• Но обходить селекторы в @page
обычно не нужно; да и по спеке это
<page-selector-list>
• Внутри @keyframes это не обычные
селекторы – <keyframe-selector>; а
блок <keyframe-block>, хотя внутри
все те же декларации
• Все это подталкивает к новым
типам узлов, усложнению парсера и
волкера
82. Поиск цвета
70
selector {
font: 10px arial black;
animation-name: red;
whatever: green;
width: blue;
color: superpurple;
}
Ни одного!
Часть имени шрифта
"arial black"
Имя анимации
Неизвестное свойство
В width нельзя указывать цвет
Нет такого цвета
83. Повышаем ставки – давайте
найдем имена анимаций
71
Типичная задача для удаления не используемых @keyframes
84. Поиск имени анимации
72
Что является именем анимации?
selector {
animation: infinite forwards normal forwards;
animation: reverse normal forwards;
animation: "reverse" normal forwards;
animation: reverse rotate normal;
animation: "reverse" normal rotate;
}
85. Поиск имени анимации
73
selector {
animation: infinite forwards normal forwards;
animation: reverse normal forwards;
animation: "reverse" normal forwards;
animation: reverse rotate normal;
animation: "reverse" normal rotate;
}
Сдавайтесь! Это нетривиальная задача
Нет времени объяснять (с)
тут могут помочь только машины, об этом дальше
98. В 2016м нашелся готовый словарь
Mozilla Template:CSSData
84
Таблицы описания свойств из спецификаций
в формате JSON;
использовалось для генерации страниц
developer.mozilla.org
100. CSSData был составлен людьми,
и использовался для генерации страниц для людей
(developer.mozilla.org)
86
😱
О – открытие
101. Хьюстон, у нас проблемы!
• Ошибки в синтаксисе (нельзя разобрать)
• Некоторые синтаксисы ссылались
на несуществующие определения
• ...
• Люди не замечали это годами...
87
103. Забегая вперед
• Mozilla Template:CSSData – был служебным шаблоном в недрах MDN
• 20 сентября 2016 – дискуссия в багтреке CSSTree относительно словарей
• Призвали ребят из MDN
• Пропушили их разместить CSSData на github
• 19 октября 2016 появился репозиторий mdn/data
• Запушил большую часть фиксов из CSSTree, добавил JSON Schema
• 22 июня 2017 ребята из MDN опубликовали пакет mdn-data 1.0 на npm
• 🎉
89
109. Clarification `Nx` as <resolution>
• Пример нельзя было провалидировать
• Не нашел в спецификациях об этом
• Создал тикет
https://github.com/w3c/csswg-drafts/issues/461
• В CSS Working Group обсудили вопрос
• Внесены изменения CSS Values and Units Module Level 4
• Роботы победили! 🤖
95
119. Плагины/пакеты
• csstree-validator – npm пакет + консольная команда
• stylelint-csstree-validator – плагин для stylelint
• gulp-csstree – плагин для gulp
• SublimeLinter-contrib-csstree – плагин для Sublime Text
• vscode-csstree – плагин для VS Code
• atom-plugin – плагин для Atom
105
Огромное спасибо Сергею Мелюкову за его вклад и поддержку!
124. Узнать у CSSTree лексический тип
110
csstree.lexer
.matchDeclaration(this.declaration)
.isType(node, 'color')
Используется в CSSO при минификации значений цвета
127. Поиск с CSSTree
113
// найти все цвета
csstree.lexer.matchAllFragments(ast, 'Type', 'color')
// ... имена анимаций
csstree.lexer.matchAllFragments(ast, 'Type', 'keyframes-name')
// ... имена шрифтов
csstree.lexer.matchAllFragments(ast, 'Type', 'family-name')
129. Чтобы добавить новые свойства и
синтаксисы – не нужно менять код,
достаточно обновить словарь
115
Возможность экспериментировать с новыми синтаксисами,
создавать свои синтаксисы
130. Решение других задач
• Разворачивание и свертка shorthand-свойств
(например, background <-> background-*)
• Мапинг значения на initial value
• Применение не только для значений деклараций
• Исправить проблемы для сложных случаев
• ...
116
131. Почему стоит начать изучать грамматику
CSS Values and Units Module
уже сегодня
117
CSS Properties and Values API Level 1
Позволит задавать свой синтаксис
для ваших Custom properties
133. Ключевое
• Появился инструмент для работы с грамматикой
CSS Values and Units Module, которая может стать прикладной
• Приведен в порядок словарь mdn/data (теперь для машин)
• Можно искать фрагменты значений по лексическому типу
• Несколько действительно полезных инструментов –
информационных и прикладных (пощупайте!)
• Новые возможности для ваших идей
119
136. Словари
• mdn/data – описание свойств (таблицы из спек),
директив, селекторов и т.д.
• mdn/browser-compat-data – поддержка разных
возможностей (JS/CSS/API) браузерами
• known-css-properties – список известных свойств
• caniuse – поддержка браузерами некоторых частей CSS
122
137. CSS свойств
•mdn/data – 367
•Alexa Top 250 – 483
•Известных свойств – 1150
Что можно сделать:
• найти неописанное свойство
• нагуглить описание
• сделать PR с описанием в JSON
141. • Всё сложно
• Много нерешенный вопросов в обработке CSS
• Инструменты совершенствуются и переходят на
новый уровень
• Новые возможности
• Словари наше всё
• Вы можете помочь!
127