Atomic CSS Deep Dive
Валентин Ульянов
04.2024
Atomic CSS Deep Dive
Валентин Ульянов
Обо мне
В IT больше 8 лет
Делаю бэкенд на Node.js и тулинг
Разрабатываю open source проект
Выступаю на конференциях и веду IT-сообщество в Питере
Я и Atomic CSS
В теме с 2018
Смотрел все инструменты, у которых >20 звезд на гитхабе
Я и Atomic CSS
В теме с 2018
Смотрел все инструменты, у которых >20 звезд на гитхабе
3 года карьеры много верстал
Я и Atomic CSS
В теме с 2018
Смотрел все инструменты, у которых >20 звезд на гитхабе
3 года карьеры много верстал
В разработку своего инструмента вложил >1000 часов
Содержание
База
State of Atomic CSS
Сравнение инструментов и технические делати
Как устроены утилиты: нейминг, синтаксис и значения
Конфигурирование
JIT engine
Заключение
Почему Atomic CSS
В сравнении с рукописным CSS
Тратим меньше мыслетоплива : названия сущностей, структура каталогов
Почему Atomic CSS
В сравнении с рукописным CSS
Тратим меньше мыслетоплива : названия сущностей, структура каталогов
Меньше CSS на клиенте : стили перестают добавляться
Почему Atomic CSS
В сравнении с рукописным CSS
Тратим меньше мыслетоплива : названия сущностей, структура каталогов
Меньше CSS на клиенте : стили перестают добавляться
Быстрее пишем стили : короткие классы, переключение файлов
Актуальные и популярные инструменты
Tailwindcss
UnoCSS
Atomizer
Актуальные проблемы
Неконсистентный нейминг
Неудобно писать сложные утилиты
Актуальные проблемы
Неконсистентный нейминг
Неудобно писать сложные утилиты
Связь с рукописным CSS
Актуальные проблемы
Неконсистентный нейминг
Неудобно писать сложные утилиты
Связь с рукописным CSS
Неудобно расширять
Неконсистентный нейминг 👎
flex
=> display: flex
, но flex-auto
=> flex: 1 1 auto
Неконсистентный нейминг 👎
flex
=> display: flex
, но flex-auto
=> flex: 1 1 auto
tracking-wide
?
Неконсистентный нейминг 👎
flex
=> display: flex
, но flex-auto
=> flex: 1 1 auto
tracking-wide
=> letter-spacing: 0.025em;
Неконсистентный нейминг 👎
flex
=> display: flex
, но flex-auto
=> flex: 1 1 auto
tracking-wide
=> letter-spacing: 0.025em;
normal
?
Неконсистентный нейминг 👎
flex
=> display: flex
, но flex-auto
=> flex: 1 1 auto
tracking-wide
=> letter-spacing: 0.025em;
normal
: line-height, font-weight, letter-spacing?
Сложные утилиты 😢
[@media(any-hover:hover){&:hover}]:opacity-100
Сложные утилиты 😢
[&:not(:first-child)]:rounded-full
Сложные утилиты 😢
supports-[margin:1svw]:ml-[1svw]
Страшная тайна Atomic CSS 😱
В большинстве проектов, небольшую часть CSS вам придется написать руками!
Связь с рукописным CSS 🤡
Связь с рукописным CSS 🤡
Конфликты с CSS
Структура файлов / каталогов
Связь с рукописным CSS 🤡
Конфликты с CSS
Структура файлов / каталогов
Получение значений утилит
Связь с рукописным CSS 🤡
Конфликты с CSS
Структура файлов / каталогов
Получение значений утилит
Нет фич препроцессоров*
*Да, часть можно подключить с PostCSS, и они не всем нужны
Неудобно расширять 🥴
Неудобно расширять 🥴
Актуальное решение 😎
Atomic CSS toolkit with Sass and ergonomics for creating styles of any complexity
Не стоит хоронить Sass
Нейминг
Tailwind 😢
Opinionated названия, созвучные с CSS свойствами/значениями
Tailwind 😢
Opinionated названия, созвучные с CSS свойствами/значениями
justify-*
: content, items, self?
Tailwind 😢
Opinionated названия, созвучные с CSS свойствами/значениями
justify-*
: content, items, self?
bg-none
- убрать весь background? Нет , только background-image
Tailwind 😢
Opinionated названия, созвучные с CSS свойствами/значениями
justify-*
: content, items, self?
bg-none
- убрать весь background? Нет , только background-image
flex
=> display: flex
, но flex-auto
=> flex: 1 1 auto
Unocss (Tachyons) 😭
br-0
=> border-right-width: 0
, но br1
=> border-radius:.125rem
Unocss (Tachyons) 😭
br-0
=> border-right-width: 0
, но br1
=> border-radius:.125rem
b
: bottom, border, display: block
? Нет , это font-weight:bold
!
Unocss (Tachyons) 😭
br-0
=> border-right-width: 0
, но br1
=> border-radius:.125rem
b
: bottom, border, display: block
? Нет , это font-weight:bold
!
normal
: line-height, font-weight, letter-spacing?
Atomizer 🥱
Сокращения Emmet + додуманные
Atomizer 🥱
Сокращения Emmet + додуманные
Js(c)
=> justify-self: center
Atomizer 🥱
Сокращения Emmet + додуманные
Js(c)
=> justify-self: center
Bg(n)
=> background: none
Atomizer 🥱
Сокращения Emmet + додуманные
Js(c)
=> justify-self: center
Bg(n)
=> background: none
Bgbm(c)
=> background-blend-mode: color
mlut 😎
Единный алгоритм для всех сокращений
mlut 😎
Единный алгоритм для всех сокращений
Js-c
=> justify-self: center
mlut 😎
Единный алгоритм для всех сокращений
Js-c
=> justify-self: center
Bdr
=> border-right: 1px solid
mlut 😎
Единный алгоритм для всех сокращений
Js-c
=> justify-self: center
Bdr
=> border-right: 1px solid
Bdrd1
=> border-radius: 1px
Почему сокращения?
Лаконичный код
Удобнее писать
Чуть меньше вес кода
Почему сокращения?
Лаконичный код
Удобнее писать
Чуть меньше вес кода
Есть порог входа
Подойдут не всем
Сокращения везде
const
, int
, char
cd
, pwd
, ls
Ldar
, Star
, SubSmi
Зачем алгоритм сокращений?
Избежать коллизий с новыми свойствами/значениями в CSS
Зачем алгоритм сокращений?
Избежать коллизий с новыми свойствами/значениями в CSS
Возможность выводить свойства "в голове", а не запоминать их
Зачем алгоритм сокращений?
Избежать коллизий с новыми свойствами/значениями в CSS
Возможность выводить свойства "в голове", а не запоминать их
Сокращения Emmet неплохи, но в них нет четких правил (confirmed by @sergeche)
Общий алгоритм сокращений кратко
Находим свойства, которые начинаются с одинаковой буквы
Общий алгоритм сокращений кратко
Находим свойства, которые начинаются с одинаковой буквы
Составляем их рейтинг
Общий алгоритм сокращений кратко
Находим свойства, которые начинаются с одинаковой буквы
Составляем их рейтинг
Выделяем группы
Общий алгоритм сокращений кратко
Находим свойства, которые начинаются с одинаковой буквы
Составляем их рейтинг
Выделяем группы
Составляем сокращения внутри групп
I. Алгоритм сокращения одной сущности
Название сокращаем до первой буквы свойства/значения
color
=> C
II. Алгоритм сокращения одной сущности
Если название из N слов, то берется первая буква из каждого слова
color-adjust
=> Ca
III. Алгоритм сокращения одной сущности
Если два названия имеют одну и ту же начальную букву, то в следующем названии, при сортировке их по рейтингу, добавляется буква
color
=> C
cursor
=> Cs
IV. Алгоритм сокращения одной сущности
Если название из N слов, то буква добавляется в соответствующем по порядку слове
color
=> C
cursor
=> Cs
color-scheme
=> Csc
I. Порядок добавления буквы
Согласная следующего слога
cursor
=> Cs
I. Порядок добавления буквы
Согласная следующего слога
cursor
=> Cs
Если следующий слог начинается на гласную, то берется ближайшая предыдущая согласная от нее
II. Порядок добавления буквы
Следующая согласная
content
=> Сt
contain
=> Cn
III. Порядок добавления буквы
Следующая гласная (без перескока через согласную)
content
=> Сt
counter -increment
=> Co i
Слабые места 🫣
Популярность свойств меняется
Слабые места 🫣
Популярность свойств меняется
Редкие длинные свойства может быть сложно вспомнить
Слабые места 🫣
Популярность свойств меняется
Редкие длинные свойства может быть сложно вспомнить
Возможны спорные ситуации, по мере развития CSS
Синтаксис
Tailwind 😢
Нет хотя бы подобия спецификации
Tailwind 😢
Нет хотя бы подобия спецификации
Ad-hoc с arbitrary частями
Tailwind: утилита и значение 😢
Tailwind: утилита и значение 😢
util-value
-util-2
- отрицательные значения
Tailwind: утилита и значение 😢
util-value
-util-2
- отрицательные значения
util-[42px]
- произвольные значения
Tailwind: утилита и значение 😢
util-value
-util-2
- отрицательные значения
util-[42px]
- произвольные значения
[css-prop:value]
- произвольное CSS свойство и значение
Tailwind: variants 😢
variant:util-value
- селекторы и некоторые at-rules
Tailwind: variants 😢
variant:util-value
- селекторы и некоторые at-rules
group/name:util-value
- группы с именами
Tailwind: variants 😢
variant:util-value
- селекторы и некоторые at-rules
group/name:util-value
- группы с именами
@md:util-value
- container queries
Tailwind: arbitrary variants 😢
variant-[.class]:util
- произвольные значения variant
Tailwind: arbitrary variants 😢
variant-[.class]:util
- произвольные значения variant
[&:nth-child(3)]:util
- произвольный variant
Tailwind: arbitrary variants 😢
variant-[.class]:util
- произвольные значения variant
[&:nth-child(3)]:util
- произвольный variant
@[17.5rem]:util
- container queries
Atomizer 🥱
Есть спецификация!
Покрывает мало фич CSS
Atomizer 🥱
[<context>[:<pseudo-class>]<combinator>]<Style>[(<value>,<value>?,...)][<!>][:<pseudo-class>][::<pseudo-element>][--<breakpoint_identifier>]
mlut: components syntax 😎
@:ah_O1_h
mlut: components syntax 😎
@:ah_O1_h
=>
@media (any-hover) {
.\@\:ah_O1_h:hover {
opacity: 1
}
}
Зачем проектировать синтаксис?
Основная цель - концептуальная близость с CSS для органичного развития вместе с ним
Minimum opinions - maximum standards!
Зачем проектировать синтаксис?
Меньше учить "фантазийных" сущностей
Зачем проектировать синтаксис?
Меньше учить "фантазийных" сущностей
Избежать (минимизировать) конфликты с CSS
Зачем проектировать синтаксис?
Меньше учить "фантазийных" сущностей
Избежать (минимизировать) конфликты с CSS
Удобство написания
Зачем проектировать синтаксис?
Меньше учить "фантазийных" сущностей
Избежать (минимизировать) конфликты с CSS
Удобство написания
Получить высокую выразительность для реализации наибольшего количества фич CSS
Utility components syntax
Синтаксис, в котором утилита разделяется на компоненты , каждый из которых, соответствует части CSS-правила
Utility components syntax
@:ah_O1_h
Utility components syntax
@:ah _O1_h
=>
@media (any-hover) {
}
Utility components syntax
@:ah _O1_h
=>
@media (any-hover) {
.\@\:ah_O1_h {
}
}
Utility components syntax
@:ah _O 1 _h
=>
@media (any-hover) {
.\@\:ah_O1_h {
opacity : 1
}
}
Utility components syntax
@:ah _O 1_h
=>
@media (any-hover) {
.\@\:ah_O1_h:hover {
opacity : 1
}
}
CSS at-rule: брейкпоинты, @supports, etc
CSS at-rule: брейкпоинты, @supports, etc
pre-states - часть селектора перед классом утилиты
CSS at-rule: брейкпоинты, @supports, etc
pre-states - часть селектора перед классом утилиты
Имя
Значение
CSS at-rule: брейкпоинты, @supports, etc
pre-states - часть селектора перед классом утилиты
Имя
Значение
post-states - часть селектора после класса утилиты
Конвертация в mlut
Конвертация - превращение сокращения из названия класса в реальную CSS-сущность
Конвертация в mlut
Конвертация - превращение сокращения из названия класса в реальную CSS-сущность
Значение
Часть селектора
Часть at-rule: название, CSS-свойство внутри, etc
Селекторы в CSS
Simple selector - 1 условие: .class
, #id
, element
Селекторы в CSS
Simple selector - 1 условие: .class
, #id
, element
(Pseudo-)Compound selector - N простых без комбинаторов:
.class[attr]
, element.class
Селекторы в CSS
Simple selector - 1 условие: .class
, #id
, element
(Pseudo-)Compound selector - N простых без комбинаторов:
.class[attr]
, element.class
Complex selector - N simple/compound c комбинаторами:
.class:hover + .item
Селекторы в CSS
Simple selector - 1 условие: .class
, #id
, element
(Pseudo-)Compound selector - N простых без комбинаторов:
.class[attr]
, element.class
Complex selector - N simple/compound c комбинаторами:
.class:hover + .item
Selector list - comma-separated список из simple/compound/complex:
.class, .item + .item, a.active
States в mlut
States - это упрощенный selector list
States в mlut
States - это упрощенный selector list
:
- объединение стейтов
,
- разделение на список
<empty>:
- пробел
Bgc -red_h,f
=>
.Bgc-red_h\,f {
background-color : red
}
Bgc -red_h,f
=>
.Bgc-red_h\,f:hover,
.Bgc-red_h\,f:focus {
background-color : red
}
^:lc:> _D-f
=>
.-Ctx:last-child > .\^\:lc\>_D-f {
}
^:lc:> _D -f
=>
.-Ctx:last-child > .\^\:lc\>_D-f {
display : flex
}
Conditional at-rules в CSS
Conditions - операторы, скобки, features / queries: (hover) and (min-width: 20rem)
Conditional at-rules в CSS
Conditions - операторы, скобки, features / queries: (hover) and (min-width: 20rem)
Операторы - логические: and
, or
, not
Conditional at-rules в CSS
Conditions - операторы, скобки, features / queries: (hover) and (min-width: 20rem)
Операторы - логические: and
, or
, not
Features - выражения, функции, etc: (pointer: fine)
, style(color: green)
Conditional at-rules в CSS
Conditional at-rules в CSS
Состав очень разный
Можно строить сложные выражения, используя операторы
Conditional at-rules в CSS
Состав очень разный
Можно строить сложные выражения, используя операторы
Можно вкладывать друг в друга
At-rules в mlut
Breakpoints: lg
, sm:md
- отдельный подсинтаксис
Rules: @media
, @supports
, etc
At-rules в mlut
Breakpoints: lg
, sm:md
- отдельный подсинтаксис
Rules: @media
, @supports
, etc
Для составления сложных выражений:
Rules
У каждого правила свое:
Rules
У каждого правила свое:
Сокращение: m
, s
, c
Конвертер - превращает сокращения в цепочку CSS-выражений
Rules
У каждого правила свое:
Сокращение: m
, s
, c
Конвертер - превращает сокращения в цепочку CSS-выражений
Кастомные значения - алиасы для часто используемых цепочек
Rules
У каждого правила свое:
Сокращение: m
, s
, c
Конвертер - превращает сокращения в цепочку CSS-выражений
Кастомные значения - алиасы для часто используемых цепочек
Синтаксис закрывает весь класс фич
@:dm-s :h>=20r_Mxw35r
=>
@media (display-mode: standalone) {
}
@:dm-s:h>=20r _Mxw35r
=>
@media (display-mode: standalone) and (min-height: 20rem) {
}
@:dm-s:h>=20r _Mxw35r
=>
@media (display-mode: standalone) and (min-height: 20rem) {
.\@\:dm-s\:h\>\=20r_Mxw35r {
}
}
@:dm-s:h>=20r _Mxw 35r
=>
@media (display-mode: standalone) and (min-height: 20rem) {
.\@\:dm-s\:h\>\=20r_Mxw35r {
max-width : 35rem
}
}
At-rules можно комбинировать!
@s:apcr4/3@:dm_Mxw40u
At-rules можно комбинировать!
@s:apcr4/3 @:dm_Mxw40u
=>
@supports (aspect-ratio: 4/3) {
}
At-rules можно комбинировать!
@s:apcr4/3@:dm _Mxw40u
=>
@supports (aspect-ratio: 4/3) {
@media (display-mode: fullscreen) {
}
}
At-rules можно комбинировать!
@s:apcr4/3@:dm _Mxw40u
=>
@supports (aspect-ratio: 4/3) {
@media (display-mode: fullscreen) {
.\@s\:apcr4\/3\@\:dm_Mxw40u {
}
}
}
At-rules можно комбинировать!
@s:apcr4/3@:dm _Mxw 40u
=>
@supports (aspect-ratio: 4/3) {
@media (display-mode: fullscreen) {
.\@s\:apcr4\/3\@\:dm_Mxw40u {
max-width : 10rem
}
}
}
Слабые места 🫣
Нельзя (пока) написать arbitrary псевдоселектор: D-f_:pseudo
=> .D-f pseudo {...}
Слабые места 🫣
Нельзя (пока) написать arbitrary псевдоселектор: D-f_:pseudo
=> .D-f pseudo {...}
Возможны конфликты пользовательских алиасов (-myQuery
) с CSS custom media или cutsom selector
Конвертация значений
Конвертация значений
Превращение сокращения из названия класса в реальное CSS-значение
ml-1
=> margin-left: 0.5rem
D-f
=> display: flex;
Tailwind 😢
Подстановка значения из словаря в теме (theme)
Tailwind 😢
Подстановка значения из словаря в теме (theme)
Прозрачность цветов: bg-sky-500/75
Tailwind 😢
Подстановка значения из словаря в теме (theme)
Прозрачность цветов: bg-sky-500/75
Императивная конвертация, при добавлении утилиты через плагин
Tailwind 😢
Подстановка значения из словаря в теме (theme)
Прозрачность цветов: bg-sky-500/75
Императивная конвертация, при добавлении утилиты через плагин
Части arbitrary значений: custom properties, пробелы, etc
Atomizer 🥱
Ключевые слова + RTL by design
Atomizer 🥱
Ключевые слова + RTL by design
Прозрачность цветов: C(#fff.5)
Atomizer 🥱
Ключевые слова + RTL by design
Прозрачность цветов: C(#fff.5)
Custom properties
Atomizer 🥱
Ключевые слова + RTL by design
Прозрачность цветов: C(#fff.5)
Custom properties
Множественные значения: Bgp(20px,50px)
Atomizer 🥱
Ключевые слова + RTL by design
Прозрачность цветов: C(#fff.5)
Custom properties
Множественные значения: Bgp(20px,50px)
Подстановка пользовательских значения из конфига
mlut 😎
Система конвертации для почти произвольных значений
mlut 😎
Система конвертации для почти произвольных значений
Ml -1/7
=> margin-left : -14.3%
mlut 😎
Система конвертации для почти произвольных значений
Ml -1/7
=> margin-left : -14.3%
Bdrd 1r;2/5p
=> border-radius : 1rem 2px / 5%
Зачем система конвертации?
Значения свойств CSS - это сложно
Зачем система конвертации?
Значения свойств CSS - это сложно
Оставаться ближе к платформе
Зачем система конвертации?
Значения свойств CSS - это сложно
Оставаться ближе к платформе
Чтобы было удобно
Значения в CSS
Value Definition Syntax
Типы данных
Единицы измерения
Функции
Основные понятия конвертации
Конвертер - функция, которая преобразует значение из сокращенного класса в реальное CSS значение
Основные понятия конвертации
Конвертер - функция, которая преобразует значение из сокращенного класса в реальное CSS значение
Трансформер - функция, которая может еще как-то изменить готовое CSS-значение. Так же указывается в опциях
Основные понятия конвертации
Тип конвертации - список конвертеров, которые применяются к значению утилиты. Есть у каждой утилиты и если не указан явно в опциях утилиты, то применяется дефолтный
Опции утилиты
'Apcr' : (
'properties' : aspect-ratio,
'conversion' : 'num-length' , // тип конвертации
),
Общий конфиг для утилит
'conversion-types' : (
//...
'num-length' : ('num-length' , 'global-kw' , 'cust-prop' )
// ^цепочка конвертеров
),
Общая схема работы конвертации
Полное значение утилиты разбивается (по пробелам или разделителю) на простые значения
Общая схема работы конвертации
Полное значение утилиты разбивается (по пробелам или разделителю) на простые значения
Каждое простое значение проходит по цепочки конвертеров до тех пор, пока 1 из них не сработает
Общая схема работы конвертации
Полное значение утилиты разбивается (по пробелам или разделителю) на простые значения
Каждое простое значение проходит по цепочки конвертеров до тех пор, пока 1 из них не сработает
К CSS значению применяется трансформер
Общая схема работы конвертации
Полное значение утилиты разбивается (по пробелам или разделителю) на простые значения
Каждое простое значение проходит по цепочки конвертеров до тех пор, пока 1 из них не сработает
К CSS значению применяется трансформер
Итоговое значение подставляется в CSS правило
Конвертеры
@function convert-uv-number ($value , $data : ())
$value
- исходное значение
$data
- map с дополнительными данными
Конвертеры
@function convert-uv-number ($value , $data : ())
Выделенное название используется в типах конвертации
Конвертеры
@function convert-uv-number ($value , $data : ())
Выделенное название используется в типах конвертации
Применяются друг за другом
Конвертеры
@function convert-uv-number ($value , $data : ())
Выделенное название используется в типах конвертации
Применяются друг за другом
Внутри может использовать другие конвертеры
Конвертеры
@function convert-uv-number ($value , $data : ())
Выделенное название используется в типах конвертации
Применяются друг за другом
Внутри может использовать другие конвертеры
Можно написать свои
Трансформеры
@function gradient ($value , $data : ())
Применяются едоножды ко всему итоговому CSS значению
Типичный кейс: оборот значения в CSS-функцию
Кейс: утилита для градиентов
'-Gdl' : (
'properties' : background-image,
'transformer' : 'gradient' ,
'css-function' : 'linear-gradient' ,
'conversion' : 'gradient' ,
'multi-list-separator' : ',' ,
'keywords' : ('position', 'gradient' ),
),
Кейс: утилита для градиентов
'conversion-types' : (
//...
'gradient' : (
'keyword' , 'color' , 'cust-prop' , 'Pl' ,
'number' , 'angle' , 'global-kw'
),
),
Кейс: утилита для градиентов
-Gdl-r,$action;30p,red;80p,tp
Кейс: утилита для градиентов
-Gdl-r,$action;30p,red;80p,tp
=>
.-Gdl-r\,\$action\;30p\,\red\;80p\,tp {
}
Кейс: утилита для градиентов
-Gdl -r,$action;30p,red;80p,tp
=>
.-Gdl-r\,\$action\;30p\,\red\;80p\,tp {
background-image: linear-gradient (
);
}
Кейс: утилита для градиентов
-Gdl -r,$action;30p,red;80p,tp
=>
.-Gdl-r\,\$action\;30p\,\red\;80p\,tp {
background-image: linear-gradient (
to right, var(--ml-action) 30%, red 80%, transparent
);
}
Слабые места 🫣
(пока) Нет first-class поддержки CSS-функций: calc()
, clamp()
Слабые места 🫣
(пока) Нет first-class поддержки CSS-функций: calc()
, clamp()
CSS значения могут занять используемые спецсимволы: ;
, $
, ?
Настройка инструмента
Добавление значений: цвета, шрифты, ключевые слова
Настройка инструмента
Добавление значений: цвета, шрифты, ключевые слова
Создание утилит
Настройка инструмента
Добавление значений: цвета, шрифты, ключевые слова
Создание утилит
Изменение настроек: брейкпоинты, новые states
Добавить значения в Tailwind 🙂
Добавить утилиту в Tailwind 😢
Надо написать плагин!
Статическая утилита в Tailwind
Вручную пишите CSS(-in-JS)-правило
Будут доступны variants
Статическая утилита в Tailwind
Динамическая утилита в Tailwind
Можно добавить словарь со значениями
Динамическая утилита в Tailwind
Можно добавить словарь со значениями
Будет доступен arbitrary синтаксис
Динамическая утилита в Tailwind
Можно добавить словарь со значениями
Будет доступен arbitrary синтаксис
Будут доступны variants
Динамическая утилита в Tailwind
Добавить значения в Unocss 🙂
Добавить утилиту в Unocss 🥴
Добавить утилиту в Unocss 🥴
Лаконичный API
Простые утилиты - в 1 строку
Добавить утилиту в Unocss 🥴
Лаконичный API
Простые утилиты - в 1 строку
Для сложных - пишем регулярки и императивную конвертацию
Добавить утилиту в Unocss 🥴
mlut 😎
Все расширения в одном конфиге за пару строк кода
mlut 😎
Все расширения в одном конфиге за пару строк кода
Утилиты и их значения
States
At-rules
Breakpoints и общие настройки
Добавить утилиту в mlut
Простая утилита в mlut из коробки
Числовые значения: Mm1r => margin-magick: 1rem
Простая утилита в mlut из коробки
Числовые значения: Mm1r => margin-magick: 1rem
Глобальные ключевые слова: Mm-ih => inherit
Простая утилита в mlut из коробки
Числовые значения: Mm1r => margin-magick: 1rem
Глобальные ключевые слова: Mm-ih => inherit
Custom properties: Mm-$myCard?200 => var(--ml-myCard, 200px)
Простая утилита в mlut из коробки
Числовые значения: Mm1r => margin-magick: 1rem
Глобальные ключевые слова: Mm-ih => inherit
Custom properties: Mm-$myCard?200 => var(--ml-myCard, 200px)
Несколько значений: Mm10p;1/3 => 10% 33.3333%
Диспетчеризация
Поиск и выбор, какая функция будет вызываться для типа данных
Диспетчеризация
Поиск и выбор, какая функция будет вызываться для типа данных
Статическая - на этапе компиляции
Динамическая - в рантайме
Статическая диспетчеризация
Динамическая диспетчеризация (ДД)
ДД в mlut
Инструменты старого поколения: AOT
Генерируем over9000 утилит
Инструменты старого поколения: AOT
Генерируем over9000 утилит
Смотрим, какие используются
Инструменты старого поколения: AOT
Генерируем over9000 утилит
Смотрим, какие используются
Удаляем лишние
Проблемы старых инструментов
Проблемы старых инструментов
Произвольные значения
Постоянно надо редактировать конфиг
Проблемы старых инструментов
Произвольные значения
Постоянно надо редактировать конфиг
Большой бандл CSS в режиме разработки
Инструменты нового поколения: JIT
Смотрим, какие утилиты используются
Генерируем только их
Общая схема работы JIT движка
Находим файлы с контентом
Общая схема работы JIT движка
Находим файлы с контентом
Сканируем их и достаем утилиты
Общая схема работы JIT движка
Находим файлы с контентом
Сканируем их и достаем утилиты
Генерируем CSS для найденных утилит
Tailwind 🥴
PostCSS плагин: AST, интеграции, экосистема
Tailwind 🥴
PostCSS плагин: AST, интеграции, экосистема
Oxide - новый движок в v4
Unocss 😎
Самописный генератор утилит
Unocss 😎
Самописный генератор утилит
Самый быстрый
Unocss 😎
Самописный генератор утилит
Самый быстрый
Тесная интеграция с небольшим количеством сборщиков
Unocss 😎
Самописный генератор утилит
Самый быстрый
Тесная интеграция с небольшим количеством сборщиков
Много дополнительных фич: attributify, shortcuts, compilation, etc
Atomizer 🙂
Самописный генератор утилит
Atomizer 🙂
Самописный генератор утилит
Относительно простой, но с legacy-зависимостями
Atomizer 🙂
Самописный генератор утилит
Относительно простой, но с legacy-зависимостями
Хорошая интеграция с большинством сборщиков: unplugin
mlut 🥴
Бэк: Sass
Генератор утилит и конфиги
CSS библиотека
Компилятор Sass
Связь Sass и JS
Получение данных из Sass-конфига
Связь Sass и JS
Получение данных из Sass-конфига
Передача утилит в генератор
Sass in JS
Загружаем код нужного Sass-модуля
Sass in JS
Загружаем код нужного Sass-модуля
Дописываем в него код
Sass in JS
Загружаем код нужного Sass-модуля
Дописываем в него код
Компилируем итоговый скрипт в CSS
Sass in JS
Загружаем код нужного Sass-модуля
Дописываем в него код
Компилируем итоговый скрипт в CSS
(при необходимости) Достаем данные из вывода
Особенности работы с Sass
Нет рантайма . Выручает нативный компилятор на Dart: sass-embedded
Особенности работы с Sass
Нет рантайма . Выручает нативный компилятор на Dart: sass-embedded
Мало фич в языке . Нет классов, regexp и т.д. Но есть кое-что из ФП
Особенности работы с Sass
Нет рантайма . Выручает нативный компилятор на Dart: sass-embedded
Мало фич в языке . Нет классов, regexp и т.д. Но есть кое-что из ФП
Максимальная интеграция с CSS . Работа с селекторами, типы данных, перевод структур данных в значения
Инсайты
Не бойтесь безумных идей
Попробуйте пойти до конца, докапаться до сути проблемы
Инсайты
Не бойтесь безумных идей
Попробуйте пойти до конца, докапаться до сути проблемы
Неудача - тоже результат
Зачем?
Решение проблем
State Of CSS: показать сообществу новые идеи
Зачем?
Решение проблем
State Of CSS: показать сообществу новые идеи
Мечта - full time open source
Вопросы?
Презентация: