[Перевод] Atomic CSS здорового человека. UnoCSS

Продолжение перевода статьи »Reimagine Atomic CSS» двухлетней давности одного из членов команды Vue core Anthony Fu, автора UnoCSS, в которой рассматривается уже сам UnoCSS

Часть первая.

2d65cff54dc22627ba5a1703e30ad36b.png

Введение в UnoCSS

UnoCSS — мгновенный (instant) атомарный CSS-движок с максимальной производительностью и гибкостью.

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

Двигатель

UnoCSS — это движок, а не фреймворк, поскольку в нем нет ядерных утилит — все функциональные возможности предоставляются через предустановки или встроенные конфигурации.

Мы представляем себе, что UnoCSS сможет имитировать функциональность большинства существующих атомарных CSS-фреймворков. И, возможно, будет использован в качестве движка для создания новых атомарных CSS-фреймворков! Например:

import UnocssPlugin from '@unocss/vite'

// the following presets do not exist at this moment,
// contribution welcome!
import PresetTachyons from '@unocss/preset-tachyons'
import PresetBootstrap from '@unocss/preset-bootstrap'
import PresetTailwind from '@unocss/preset-tailwind'
import PresetWindi from '@unocss/preset-windi'
import PresetAntfu from '@antfu/oh-my-cool-unocss-preset'

export default {
  plugins: [
    UnocssPlugin({
      presets: [
        // PresetTachyons,
        PresetBootstrap,
        // PresetTailwind,
        // PresetWindi,
        // PresetAntfu

        // pick one... or multiple!
      ]
    })
  ]
}

Давайте посмотрим, как это стало возможным:

Интуитивный и полностью настраиваемый

Основные цели UnoCSS — интуитивность и настраиваемость. Он позволяет создавать собственные утилиты буквально за считанные секунды.

Далее вы найдете краткое руководство:

Статические правила

Атомарный CSS может оказаться огромным по объему. Важно, чтобы определение правил было простым и легко читаемым. Чтобы создать пользовательское правило для UnoCSS, вы можете написать его следующим образом:

rules: [
  ['m-1', { margin: '0.25rem' }]
]

Когда m-1 будет обнаружен в кодовой базе пользователя, будет сгенерирован следующий CSS:

.m-1 { margin: 0.25rem; }

Динамические правила

Чтобы сделать его динамическим, измените matcher на RegExp, а body на функцию:

rules: [
  [/^m-(\d+)$/, ([, d]) => ({ margin: `${d / 4}rem` })],
  [/^p-(\d+)$/, match => ({ padding: `${match[1] / 4}rem` })],
]

Первым аргументом функции body является результат совпадения, поэтому вы можете деструктурировать его, чтобы получить группы совпадений RegExp.

Например, при использовании:

Соответствующий CSS будет сгенерирован:

.m-100 { margin: 25rem; }
.m-3 { margin: 0.75rem; }
.p-5 { padding: 1.25rem; }

Вот и все. Осталось только добавить другие утилиты, использующие тот же шаблон, и теперь у вас есть свой собственный атомарный CSS!

Варианты (Variants)

Варианты в UnoCSS также просты и в то же время мощны. Вот несколько примеров:

variants: [
  // support `hover:` for all rules
  {
    match: s => s.startsWith('hover:') ? s.slice(6) : null,
    selector: s => `${s}:hover`,
  },
  // support `!` prefix to make the rule important
  {
    match: s => s.startsWith('!') ? s.slice(1) : null,
    rewrite: (entries) => {
      // append ` !important` to all css values
      entries.forEach(e => e[1] += ' !important')
      return entries
    },
  }
]

Конфигурации вариантов могут быть немного расширены. Из-за большого объема статьи я опущу подробное объяснение здесь, вы можете обратиться к документации за более подробной информацией.

Пресеты (presets)

Сейчас вы можете упаковать свои пользовательские правила и варианты в пресеты и поделиться ими с другими — или создать даже свой собственный атомарный CSS-фреймворк поверх UnoCSS!

Кроме того, мы поставляем несколько пресетов, чтобы вы могли быстро освоить их.

Однако стоит упомянуть, что стандартный @unocss/preset-uno пресет (все еще экспериментальный) является общим суперсетом популярных фреймворков, включая Tailwind CSS, Windi CSS, Bootstrap, Tachyons и т.д.

Например, оба ml-3 (Tailwind), ms-2 (Bootstrap), ma4 (Tachyons), mt-10px (Windi CSS) являются валидными.

.ma4 { margin: 1rem; }
.ml-3 { margin-left: 0.75rem; }
.ms-2 { margin-inline-start: 0.5rem; }
.mt-10px { margin-top: 10px; }

Узнайте больше о предустановке по умолчанию.

Гибкость

До сих пор мы показывали, как можно использовать UnoCSS для имитации поведения Tailwind — хотя мы сделали так, что имитировать Tailwind своими силами очень легко, это само по себе, вероятно, не будет иметь большого значения для пользователей.

Давайте раскроем истинную силу UnoCSS:

Режим атрибутирования (Attributify Mode)

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

Вот так преобразуется ваш код Tailwind:

к:

Это не только обеспечивает лучшую организацию по категориям, но и избавляет вас от повторного ввода одних и тех же префиксов.

В UnoCSS мы реализовали режим Attributify Mode, используя только один вариант и один экстрактор с менее чем 100 строками кода в общей сложности! Что еще более важно, он напрямую работает для любых пользовательских правил, которые вы определили!

В дополнение к режиму Windi’s Attributify Mode мы также поддерживаем атрибуты без значений с помощью нескольких строк изменений:

теперь можно

Режим атрибутирования предоставляется через пресет @unocss/preset-attributify, подробное использование смотрите в его документации.

Чистые CSS-иконки

Если вы читали мой предыдущий пост Journey with Icons Continues, то должны знать, что я очень увлечен иконками и активно ищу решения для иконок. На этот раз, благодаря гибкости UnoCSS, у нас даже могут быть чисто CSS-иконки! Да, вы не ослышались, только на CSS и ноль JavaScript! Давайте посмотрим, как это выглядит:


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

И снова эта функция написана менее чем на 100 строк кода. Ознакомьтесь с реализацией пресета @unocss/preset-icons, чтобы узнать, как это работает!

Обновление: Читайте мой новый пост Иконки в чистом CSS, чтобы узнать об этом больше!

Я надеюсь, что эти пресеты дадут вам общее представление о том, насколько гибким является UnoCSS. Учитывая, что он все еще находится на очень ранней стадии, нам еще предстоит исследовать множество возможностей.

Область видимости (scoping)

Еще одна проблема, с которой я столкнулся при использовании Tailwind/Windi, — это префлайт (preflight). Preflight сбрасывает нативные элементы и обеспечивает некоторый откат для переменных CSS. Это замечательно при разработке нового приложения, использующего исключительно Tailwind/Windi, но когда вы хотите заставить их работать с другими фреймворками пользовательского интерфейса или совместно использовать некоторые компоненты с помощью утилит Tailwind, префлайт часто вносит множество конфликтов, которые ломают существующий пользовательский интерфейс.

Поэтому UnoCSS сделал еще один агрессивный шаг, отказавшись от поддержки префлайтов. Вместо этого он оставил контроль над сбросом CSS полностью на усмотрение пользователей (или фреймворков поверх UnoCSS), которые могут использовать то, что соответствует их потребностям (Normalize.css, Reset.css, сброс UI-фреймворков и т. д.)

Это также позволяет UnoCSS иметь больше возможностей для CSS Scoping. Например, у нас есть экспериментальный режим scoped-vue в плагине Vite для генерации scoped-стилей для каждого компонента, чтобы вы могли безопасно поставлять их как библиотеку компонентов, используя атомарный CSS, не беспокоясь о конфликте с CSS пользователей. Например: