Утилитарный CSS с Tailwind

Автор Энди Ли

В последние несколько лет утилитарный CSS стал популярной тенденцией в области front-end. Возможно, вы видели, что он упоминается вместе с инструментом под названием Tailwind CSS.

Так что же такое «полезность»?

Какую проблему решает этот подход?

Как в это вписывается Tailwind?

И самое главное: как применить Tailwind в приложении Vue.js?

Мы собираемся ответить на все эти вопросы в этом руководстве. А если вы предпочитаете смотреть видео, вы можете ознакомиться с курсом Utility-First CSS with Tailwind от Vue Mastery. (Первые три урока этого курса соответствуют содержанию этой статьи).


Что такое Utility-first CSS?

Давайте начнем с классического кода CSS/HTML для демонстрации:

CSS

.container {
  background-color: lightgray;
  padding: 20px;
  width: 500px;
  margin: 20px;
}

.heading {
  font-size: 20px;
  font-family: Arial;
  margin: 0;
}
Вход в полноэкранный режим Выход из полноэкранного режима

HTML

<div class="container">
  <h1 class="heading">Utility-first CSS?</h1>
</div>
Войти в полноэкранный режим Выход из полноэкранного режима

С помощью подхода, ориентированного на полезность, вышеприведенное можно было бы рефакторизовать в нечто подобное:

CSS

.bg-light-gray { background-color: lightgray; }
.p-20px { padding: 20px; }
.w-500px { width: 500px; }
.m-20px { margin: 20px; }
.font-20px { font-size: 20px; }
.arial { font-family: Arial; }
.m-0 { margin: 0; }
Войти в полноэкранный режим Выход из полноэкранного режима

HTML

<div class="bg-light-gray p-20px w-500px m-20px">
  <h1 class="font-20px arial m-0">Utility-first CSS?</h1>
</div>
Войти в полноэкранный режим Выход из полноэкранного режима

Как видите, это просто замена высокоуровневых классов, таких как container и heading, на низкоуровневые классы, такие как bg-light-gray и p-20px.

Эти низкоуровневые классы называются утилитарными классами. Их можно рассматривать как низкоуровневые предметы дизайна с предсказуемыми именами. Поэтому их также называют атомарными классами.

Не глядя на определение h-200px, вы уже знаете, что это, вероятно, что-то вроде этого:

.h-200px {
  height: 200px
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Вам никогда не понадобится изменять класс утилиты. Если вам нужно изменить внешний вид вашего приложения, вы просто меняете его в HTML, добавляя/удаляя классы утилит.

Например, если мне больше не нужен цвет фона, я просто удалю класс bg-light-gray вот так:

<div class="p-20px w-500px m-20px">
  <h1 class="font-20px arial m-0">Utility-first CSS?</h1>
</div>
Вход в полноэкранный режим Выйти из полноэкранного режима

В то время как в традиционной установке мне пришлось бы изменить содержимое класса container следующим образом:

.container {
  /* background-color: lightgray; */
  padding: 20px;
  width: 500px;
  margin: 20px;
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Сначала это не кажется огромной разницей. Это просто вопрос изменения CSS или изменения HTML. Но это имеет огромное значение с точки зрения удобства обслуживания.

Если вы вносите изменения в CSS, вам нужно быть особенно внимательным, чтобы убедиться, что изменения не повлияют на что-то непреднамеренное. Но если вы вносите изменения, изменяя только HTML, вы точно знаете, что изменения затрагивают только тот HTML, который вы изменяете.

Главное преимущество использования служебных классов заключается в следующем: вам не нужно беспокоиться о непредвиденных последствиях добавления/удаления стилей.

Для разработчиков Vue.js это может быть не так важно, если вы уже используете <style scoped>. Но если у вас много CSS, распределенных по разным компонентам, уверенность в том, что вы знаете, на что повлияет ваше изменение, все равно очень полезна. Подход, ориентированный на полезность, сопровождается уникальной философией совместного использования кода, которая обеспечивает эту уверенность.


Хорошо, но зачем нам нужен Tailwind?

Обратите внимание, что в приведенном выше примере нам даже не пришлось использовать какой-либо фреймворк. Так зачем же нам нужен Tailwind или любой другой подобный фреймворк?

Во-первых, кто-то должен создать все эти классы CSS Utility (их сотни), поэтому либо вы создаете их сами, либо используете существующее решение с общепринятыми соглашениями об именах.

Во-вторых, фреймворк предоставляет больше полезных функций.

Например, вы можете использовать динамически генерируемый класс с произвольным значением, как это сделано здесь:

<h1 class="p-[20px]">Utility-first CSS?</h1>
Вход в полноэкранный режим Выйти из полноэкранного режима

Этот класс не существует по умолчанию, но он будет создан динамически к моменту выполнения этого кода.

Позже я расскажу подробнее о том, как создается такой динамический класс. Пока же просто знайте, что при использовании фреймворка можно получить больше полезных возможностей.

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

А сейчас давайте установим Tailwind и посмотрим, что он из себя представляет.


Настройка проекта

Эта серия уроков написана в стиле обучения через рефакторинг. Поэтому давайте сначала возьмем этот пример приложения с GitHub:

git clone https://github.com/Code-Pop/tailwind-tutorial.git
Войти в полноэкранный режим Выйти из полноэкранного режима

Это приложение не поставляется с предустановленным tailwind, поэтому давайте установим tailwind прямо сейчас:

package.json

"devDependencies": {
  "autoprefixer": "^10.4.7",
  "postcss": "^8.4.14",
  "tailwindcss": "^3.1.6",
  ...
Войти в полноэкранный режим Выйти из полноэкранного режима

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

tailwindcss — это плагин для postcss, поэтому postcss — это, по сути, движок, на котором работает tailwind. autoprefixer — это еще один плагин, позволяющий писать CSS-правила, не зависящие от браузера, и он позаботится о добавлении префиксов производителей. Мы не будем использовать autoprefixer напрямую, но он является зависимостью для Tailwind.

Далее нам нужно добавить некоторые конфигурационные файлы для tailwindcss и postcss. Мы можем сделать это с помощью данной команды:

npx tailwindcss init -p
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь у нас есть два новых файла:

  • tailwind.config.js
  • postcss.config.js

Нам не нужно изменять конфигурацию postcss. Но в конфигурации tailwind нам нужно указать Tailwind, какие файлы нужно сканировать:

📃 tailwind.config.js

module.exports = {
  content: [
    "./src/**/*.vue",
  ],
  ...
Вход в полноэкранный режим Выйти из полноэкранного режима

Мы указываем ему сканировать только файлы с расширением .vue. Мы будем использовать только служебные классы в файлах компонентов.

Наконец, нам нужно перейти к файлу main.css и добавить следующее в верхней части файла:

📃 src/assets/main.css

@tailwind utilities;
Вход в полноэкранный режим Выйти из полноэкранного режима

Это позаботится об импорте в наше приложение всех CSS, которые сгенерирует для нас tailwind.

По желанию:

Если вам нужен сброс стилей, вы можете сделать @tailwind base; Поскольку это приложение уже имеет свои собственные базовые стили, мы не будем использовать @tailwind base. Но если вы начинаете с совершенно нового приложения, то это хорошая идея, чтобы использовать его.

Вы также можете использовать @tailwind components;, если хотите использовать библиотеку компонентов TailwindUI. Но в этой серии уроков мы будем использовать только Tailwind CSS. TailwindUI и Tailwind CSS — это два связанных, но разных проекта.

Теперь, когда все правильно настроено, давайте перейдем к компонентам.


Компоненты

В этом приложении есть два компонента: App.vue и ProductDisplay.vue.

Компонент App импортирует и рендерит компонент ProductDisplay. Большинство стилей находится в компоненте ProductDisplay.

Если вы запустите приложение:

npm run dev
Войдите в полноэкранный режим Выйти из полноэкранного режима

В браузере это выглядит следующим образом:

В этом руководстве мы начнем с более простого компонента App.vue. (Если вы хотите увидеть полный рефакторинг App.vue и ProductDisplay.vue, вы можете ознакомиться с курсом Utility-First CSS with Tailwind).


Рефакторинг

Процесс рефакторинга очень прост. Нам просто нужно поменять местами каждое из этих CSS-правил с соответствующими им полезными классами:

📃 src/App.vue

Как вы можете видеть, некоторые правила CSS сопоставлены с несколькими классами утилит, например, правило границы и правило градиента. Так что это не всегда сопоставление один к одному.

Далее мы помещаем классы в HTML:

📃 src/App.vue

<template>
  <div class="h-[60px] mb-[25px] bg-gradient-to-r from-[#16c0b0] to-[#84cf6a]">
  </div>
  <div class="my-[25px] mx-[100px] float-right border border-solid border-light-gray p-[30px] bg-white">
    Cart({{ cart.length }})
  </div>
  ...
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь можно удалить исходный CSS:

📃 src/App.vue

<style scoped>
/* 
.nav-bar {
  height: 60px;
  margin-bottom: 25px;
  background: linear-gradient(90deg, #16c0b0, #84cf6a);
}

.cart {
  margin: 25px 100px;
  padding: 30px;
  border: 1px solid #d8d8d8;
  background-color: white;
  float: right;
} */
</style>
Войти в полноэкранный режим Выйти из полноэкранного режима

Если вы снова посмотрите на это в браузере, все должно выглядеть точно так же, как и раньше:


Классы

Давайте пройдемся по этим полезным классам один за другим:

📃 src/App.vue

<template>
  <div class="h-[60px] mb-[25px] bg-gradient-to-r from-[#16c0b0] to-[#84cf6a]">
  </div>
  <div class="my-[25px] mx-[100px] p-[30px] border border-solid border-[#d8d8d8] bg-white float-right">
    Cart({{ cart.length }})
  </div>
  ...
Вход в полноэкранный режим Выход из полноэкранного режима
  • Комбо из bg-gradient-to-r, from-[#16c0b0] и to-[84cf6a] используются для правила градиента: background: linear-gradient(-90deg, #84cf6a, #16c0b0). to-r означает «вправо». Также можно использовать to-l для противоположного направления градиента.
  • Наконец, float-right — это float: right.

Глядя на эти классы, вы можете задаться вопросом: как узнать имя класса для каждой конкретной ситуации? В конце концов, вам нужно знать имя класса, чтобы использовать его.

Вот тут-то и пригодится сайт документации Tailwind. Все, что вам нужно сделать, это найти интересующее вас свойство CSS, и он покажет вам полезные классы, которые вы можете использовать.

Например, если вы хотите задать размер шрифта font-size элемента, но не знаете, какой класс использовать, просто найдите «font-size» в документации Tailwind:


Скобки против отсутствия скобок

Вы могли заметить, что некоторые классы утилит имеют скобки, а некоторые — нет.

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

h-[60px] можно заменить на h-16, что переводится как 64px.

Это не совсем то же самое, что 60px, но в данном случае это подходит. Я также могу заменить mb-[25px] на mb-6, my-[25px] на my-6, mx-[100px] на mx-24, и p-[30px] на p-7.

📃 src/App.vue

<template>
  <div class="h-16 mb-6 bg-gradient-to-r from-[#16c0b0] to-[#84cf6a]">
  </div>
  <div class="my-6 mx-24 p-7 border border-solid border-[#d8d8d8] bg-white float-right">
    Cart({{ cart.length }})
  </div>
  ...
Вход в полноэкранный режим Выход из полноэкранного режима

Опять же, эти новые классы не соответствуют первоначальным размерам, но выглядят гораздо чище.

Вы можете найти больше таких классов вместе с соответствующими размерами px в документации:

Аналогично, мы могли бы заменить Hex-коды цветов на удобные для пользователя названия, которые Tailwind предоставляет из коробки, например teal-500 и green-500:

📃 src/App.vue

<div class="h-16 mb-6 bg-gradient-to-r from-teal-500 to-green-500">
Вход в полноэкранный режим Выход из полноэкранного режима

Список цветов и их названия вы можете найти в документации.

Но цвета, которые нам нужны здесь, очень специфичны, поэтому мы будем придерживаться шестнадцатеричных кодов с синтаксисом скобок:

📃 src/App.vue

<div class="h-16 mb-6 bg-gradient-to-r from-[#16c0b0] to-[#84cf6a]">
Вход в полноэкранный режим Выйти из полноэкранного режима

Как раз вовремя

Как вы уже могли заметить, эти динамические классы не существуют по умолчанию:

  • from-[#16c0b0]
  • to-[#84cf6a]
  • border-[#d8d8d8]

Поскольку их имена содержат произвольные значения, Tailwind не сможет создать эти классы заранее.

Вместо этого механизм Tailwind Just-In-Time (JIT) должен просканировать наш код, чтобы найти эти классы и создать фактическое определение класса для каждого из них.

Например, когда Tailwind видит border-[#d8d8d8] в вашем HTML, он создаст следующее определение класса для вас:

.border-[#d8d8d8] {
  --tw-border-opacity: 1;
  border-color: rgb(216 216 216 / var(--tw-border-opacity));
}
Вход в полноэкранный режим Выход из полноэкранного режима

На самом деле, классы обычного вида также не подготавливаются заранее:

  • h-16
  • mb-6
  • my-6
  • mx-24
  • p-7

Как и динамические классы, механизм Tailwind JIT будет сканировать и рендерить CSS для каждого из этих классов в режиме реального времени.

Каждый раз, когда вы изменяете и сохраняете свой код, JIT-движок будет запускаться и компилировать нужные стили. Конечно, это делается только в режиме разработки. Для производства CSS достаточно собрать один раз.

Поэтому вы можете задаться вопросом… Если JIT-движок все равно должен генерировать оба этих типа классов, то чем они отличаются друг от друга?

Готовые классы имеют разумные названия, документированы с предсказуемыми соглашениями об именовании и настраиваются.

Поэтому, когда это возможно, используйте готовые классы. А если вам нужно что-то более индивидуальное в рамках вашего руководства по стилю, вы можете расширить Tailwind своими собственными конфигурациями.


Продолжение

Если вы хотите продолжить изучение различных продвинутых тем Tailwind, таких как использование Tailwind для отзывчивого дизайна и настройка Tailwind, ознакомьтесь с курсом Utility-First CSS with Tailwind от Vue Mastery.

Первоначально опубликовано на https://www.vuemastery.com 29 августа 2022 года.


Оцените статью
devanswers.ru
Добавить комментарий