Tailwind CSS на данный момент обгоняет по популярности все остальные CSS-фреймворки. По своей сути это utility-first CSS-фреймворк. В отличие от Bootstrap или Bulma, он не предоставляет готовые компоненты, а дает набор низкоуровневых utility-классов, из которых можно собрать интерфейс прямо в HTML.
Пример использования:
|
1 2 3 |
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"> Click me </button> |
В этой статье мы рассмотрим такие вопросы:
- Подключение Tailwind CSS
- HTML и классы Tailwind CSS
- Группа Layout
- Группа Flexbox & Grid
- Отступы и размеры
- Текст и шрифты
- Цвета и фон
- Адаптивность (Responsive)
- Hover, Focus, Active
- Использование ::before и ::after
- Dark Mode - темная тема
Почему Tailwind стал таким популярным
Плюсы:
- Очень быстрая разработка интерфейсов;
- Полный контроль над дизайном;
- Нет «мертвого» CSS;
- Удобная адаптивность;
- Встроенная поддержка dark mode;
- Отличная кастомизация.
Минусы:
- HTML выглядит перегруженным немаленьким количеством классов в каждом элементе;
- Нужно привыкнуть к синтаксису;
- Без сборки (build step) использовать неудобно.
Подключение Tailwind CSS
Несмотря на то, что Tailwind CSS - это CSS-фреймворк, его нужно подключать через тег <script> с CDN (для тестов и демо, но не для готового проекта):
|
1 |
<script src="https://cdn.tailwindcss.com"></script> |
Можно даже кастомизировать:
|
1 2 3 4 5 6 7 8 9 10 11 |
<script> tailwind.config = { theme: { extend: { colors: { brand: '#1e40af', } } } } </script> |
В различные JavaScript-фреймворки и библиотеки Tailwind CSS нужно подключать в терминале несколькими командами + добавлять настройки и директиву @import в основной файл проекта. Как это сделать для множества библиотек, можно найти на официальном сайте. Про подключение Tailwind CSS для проекта React+Vite также можно прочитать в отдельной статье.
Поскольку любые такие проекты собираются воедино какой-либо командой в терминале типа npm run dev для проекта React+Vite, одновременно происходит и сборка всех классов Tailwind CSS, которые нужны для текущего проекта.
HTML и классы Tailwind CSS
В коде html-разметки вы будете использовать, как правило, набор классов Tailwind CSS:
|
1 2 3 4 5 |
<div className="min-h-screen flex items-center justify-center"> <h1 className="text-3xl font-bold text-blue-600"> Hello Tailwind </h1> </div> |
Подход Tailwind CSS в данном случае такой - каждый класс отвечает за какое-то одно свойство: класс flex за свойство display: flex, класс items-center за align-items: center, класс font-bold за font-weight: bold и т.п. Таким образом, чтобы манипулировать этими классами, нужно очень даже неплохо знать CSS с точки зрения свойство: значение, чтобы даже интуитивно можно было писать свои классы, не заглядывая в документацию.
Основные группы классов Tailwind CSS
Группа Layout
|
1 |
<div class="container mx-auto px-4"> |
Классы:
container, columns-md- контейнер и столбцы (колонки);block, flex, grid- различные варианты свойстваdisplay;hidden- спрятанные элементы;absolute, relative, fixed- классы для позиционирования элементов.
Группа Flexbox & Grid
|
1 2 |
<div class="flex items-center justify-between"> <div class="grid grid-cols-3 gap-6"> |
Классы:
flex-row, flex-colitems-centerjustify-betweengap-4
Пример разметки контента
See the Pen Tailwind CSS example by HTML-plus (@ambassador) on CodePen.
Отступы и размеры
|
1 |
<div class="p-6 mt-4 w-full max-w-md"> |
m, mt, mx, m-auto, mt-6- классы для назначенияmargin;p, py, pl-4, p-6- все классы для назначенияpadding;w-xs, w-lvw, w-1/2, w-full- классы для назначения ширины элемента;h-screen, h-full, h-1/2, h-42- классы для назначения высоты элемента.
Пример использования различных классов:
See the Pen Tailwind CSS example by HTML-plus (@ambassador) on CodePen.
В этом примере футере для центрирования списка из 2-х ссылок используется не ожидаемый класс text-center, который подразумевает использование такого свойства, как text-align: center, а комбинация из классов w-fit + mx-auto . "Под капотом" здесь лежат такие свойства, как width: fit-content, которое говорит, что ширина элемента равна ширине его содержимого, плюс класс mx-auto, который позволяет auto-margin распределить свободное место слева и справа от элемента ul.
Немного подробнее о классах с отступами на примере тех, что управляют свойством padding:
pобозначает отступ по всему элементу.pyобозначает отступы: padding-top и padding-bottom.pxобозначает отступ слева и отступ справа.ptобозначает верхний отступ.prобозначает отступ справа.pbобозначает нижний отступ.plобозначает отступ слева
И еще несколько классов, связанных с шириной
| Класс | CSS | Поведение |
|---|---|---|
w-full |
width: 100% |
занимает весь контейнер |
w-auto |
width: auto |
зависит от контекста |
w-fit |
width: fit-content |
ровно по контенту |
w-1/2 |
width: 50% |
половина ширины родительского элемента |
Текст и шрифты
Классы:
text-sm, text-lg, text-3xl- размеры текста можно найти в документации;font-light, font-semibold- классы для толщины шрифта и курсива;leading-tight- классы для межстрочного расстояния;uppercase- изменение начертания букв;decoration-solid- классы для подчеркивания
Цвета и фон
|
1 |
<div class="bg-gray-100 text-gray-800"> |
Классы:
bg-blue-500- для фона;text-red-600- для текста;border-gray-300- для рамки.
Tailwind использует шкалу от 50 до 950. В документации вы найдете все основные примеры.
Все цвета можно найти на сайте tailwindcolor.com.
Hover, Focus, Active
|
1 |
<button class="bg-blue-500 hover:bg-blue-600 focus:ring"> |
Поддерживаются:
- hover:
- focus:
- active:
- disabled:
- group-hover
Подробнее в документации. Но, если говорить подробнее, то наверняка вы знаете разницу между этими состояниями и заодно псевдоклассами:
| Состояние | Когда срабатывает | Для чего реально нужен |
|---|---|---|
hover |
навели мышь | визуальная реакция |
focus |
элемент активен (клик / Tab) | доступность, ввод |
active |
момент нажатия | тактильный отклик |
disabled |
недоступность элемента формы | должно отображаться визуально + специальный курсор |
group-hover |
вариант состояния, который позволяет дочернему элементу реагировать на hover родителя, а не на себя самого. | когда пользователь наводит мышь на контейнер, что-то меняется внутри него |
В качестве примера рассмотрим простую форму, в которой в поле <input type="email"> есть классы, связанные и с hover:, и с focus:, а в элементе <button> - hover: и active:.
See the Pen Tailwind CSS form hover: and focus: example by HTML-plus (@ambassador) on CodePen.
Обратите внимание, что мы отключаем здесь доступный во всех формах по умолчанию outline с помощью кода focus:outline-none. Однако заменяем его альтернативным поведением focus:ring-2 focus:ring-sky-200 для подсветки действия фокуса.
Использование класса peer в Tailwind CSS
Пример с кнопкой в состоянии disabled подразумевает вариант, когда мы используем класс peer и определенную вложенность элементов друг в друга для того, чтобы при активации чекбокса отобразить доступную кнопку. Причем делаем это не за счет JavaScript, а за счет специальных классов Tailwind CSS.
See the Pen Tailwind CSS form disabled: example by HTML-plus (@ambassador) on CodePen.
Сразу возникает вопрос - что такое peer в Tailwind CSS?
Так вот, peer — это класс-маркер, который ты ставишь на элемент, чтобы следующие элементы могли реагировать на его состояние.
|
1 2 3 4 5 |
<input type="checkbox" class="peer mr-2" /> <span class="peer-checked:bg-green-500 p-2"> Я меняюсь, если checkbox отмечен </span> |
Здесь: input содержит класс peer, т.е. от него зависит поведение соседнего/родственного элемента, span реагирует на состояние checked у input.peer, получая класс bg-green-500.
Если заглянуть "под капот" Tailwind CSS, то увидим примерно такой код:
|
1 2 3 |
.peer:checked ~ .peer-checked\:bg-green-500 { background-color: #22c55e; } |
Ключевой момент — родственный селектор ~. С точки зрения работы этого селектора, это значит следующее: если элемент с классом .peer находится в состоянии :checked, то все элементы после него с нужным классом получат стиль от классаbg-green-500.
Давайте попробуем нажать на чекбокс, чтобы посмотреть пример в действии:
See the Pen Tailwind CSS form class peer example by HTML-plus (@ambassador) on CodePen.
Очень важные ограничения peer:
Элемент с классом peer НЕ может идти ПОСЛЕ элемента, который должен реагировать на его изменение.
|
1 2 |
<div class="peer-checked:bg-red-500"></div> <input type="checkbox" class="peer" /> |
Элемент, который содержит класс peer-checked НЕ может быть вложен в другой элемент. Только тот же уровень вложенности, что и у элемента с классом peer.
|
1 2 3 4 |
<input class="peer" /> <div> <span class="peer-checked:text-red-500"></span> </div> |
Чаще всего такое поведение работает для состояний:
peer-hover:*peer-focus:*peer-checked:*peer-disabled:*peer-placeholder-shown:*
Возьмем еще пример из документации Tailwind CSS:
See the Pen Tailwind CSS form class peer example by HTML-plus (@ambassador) on CodePen.
Здесь показано, что при использовании нескольких узлов можно стилизовать состояние конкретного узла , присвоив ему уникальное имя с помощью peer/{name}класса и включив это имя в варианты, используя такие классы, как peer-checked/{name}:.
Еще один отличный пример с использованием класса peer для реализации off-canvas меню, которое выезжает в мобильной версии с левой стороны страницы. Для того чтобы посмотреть на вариант в мобильной версии, щелкните на вкладку HTML.
See the Pen Tailwind CSS form class peer mobile menu example3 by HTML-plus (@ambassador) on CodePen.
Единственный минус - это отсутствие возможности закрыть выезжающее меню. Но этот минус исправлен ниже. Хотя в следующем примере off-canvas-menu выезжает справа.
See the Pen Tailwind CSS form class peer off-canvas menu example4 by HTML-plus (@ambassador) on CodePen.
Использование group-hover
Вы можете задать поведение элементов внутри контейнера, когда наведение выполняется не на сам элемент, а на весь контейнер. Без JavaScript. Без вложенных селекторов. Без кастомного CSS.
В обычном CSS это выглядело бы так:
|
1 2 3 |
.card:hover .icon { color: blue; } |
В Tailwind CSS то же самое записывается в виде классов:
|
1 2 3 |
<div class="group"> <svg class="group-hover:text-blue-500"></svg> </div> |
Здесь group — это маркер, а не стиль.
Пример с группировкой для полей ввода вы найдете ниже.
See the Pen Tailwind CSS form hover: and focus: example by HTML-plus (@ambassador) on CodePen.
Как group-hover устроен внутри Tailwind
Шаг 1. Родитель помечается как группа: <div class="group">
Tailwind генерирует селектор:
|
1 2 3 |
.group:hover .group-hover\:text-blue-500 { color: #3b82f6; } |
Шаг 2. Дочерний элемент подписывается на hover группы: к нему добавляются классы group-hover:text-blue-500.
Это буквально значит: "применить этот стиль, когда .group находится в состоянии hover".
Когда group-hover — правильный выбор:
Карточки
- подсветить иконку
- показать кнопку
- затемнить фон
Формы
- показать подсказку
- активировать label
- подсветить иконку поля
Навигация
- dropdown
- underline
- стрелки
Если у вас интерактивность прописывается для одного элемента (кнопка, input) group-hover использовать НЕ стоит.
Псевдокласс focus-within
Псевдокласс :focus-within срабатывает на родителе, если ЛЮБОЙ его потомок получил фокус. На примере в связке HTML+ обычный CSS это выглядит так: при клике внутри поля input содержащий его div становится красным.
|
1 2 3 4 5 6 7 |
<div> <input type="text" placeholder="Login"> </div> //----------CSS--------\\ div:focus-within { background: red; } |
В Tailwind CSS вместо псевдокласса вы используете класс focus-within:* для формы, как для родителя любого элемента формы: input, textarea, select или button. Если нужно сделать что-либо для других элементов, не входящих в формы (div, p, span), тогда нужно форме добавлять класс group, а для div-а или абзаца записывать group-focus-within:*.
Пример с focus-within: в Tailwind CSS и group для подсветки формы и вывода сообщения.
See the Pen Tailwind CSS focus-within example by HTML-plus (@ambassador) on CodePen.
Здесь срабатывает такая схема действий: клик в input приводит к тому, что <form> получает focus-within, а <p> реагирует через group-focus-within.
Еще один пример с focus-within - популярное на многих сайтах dropdown, или выпадающее меню.
See the Pen Tailwind CSS dropdown example by HTML-plus (@ambassador) on CodePen.
Почему в примере мы НЕ используем hover, а именно focus-within?
| hover | focus-within |
|---|---|
| ❌ мобильные | ✅ мобильные |
| ❌ клавиатура | ✅ tab |
| ❌ закрывается при движении | ✅ стабилен |
Ну, и на сладкое - мега-меню на основе Tailwind CSS:
See the Pen Tailwind CSS dropdown menu example by HTML-plus (@ambassador) on CodePen.
Использование ::before и ::after
Псевдоэлементы ::before и ::after дают много вариантов управления контентом, причем именно с точки зрения использования еще и анимации. С точки зрения Tailwind CSS вы можете указать их таким образом:
|
1 2 3 4 |
<label> <span class="text-gray-700 after:ml-0.5 after:text-red-500 after:content-['*'] ...">Email</span> <input type="email" name="email" class="..." placeholder="you@example.com" /> </label> |
Здесь код after:content-['*'] дает нам звездочку после текста Email в label, код after:text-red-500 красит эту звездочку в красный цвет, а код after:ml-0.5 дает отступ слева от звездочки от текста. Второй пример дает нам абсолютное позиционирование блочного скошенного псевдоэлемнта ::before без контента, но с цветом фона.
See the Pen Tailwind CSS button example by HTML-plus (@ambassador) on CodePen.
Отсутствие контента также можно записать, как before:content-['']:
|
1 |
<div class="relative before:absolute before:content-['']"> |
В примере ниже у нас есть изменение кнопок при наведении с анимацией. В самих кнопках псевдоэлементы ::before и ::after используются для создания эффектов при наведении.
See the Pen Tailwind CSS button example by HTML-plus (@ambassador) on CodePen.
Анимацию создаёт комбинация классов transition-* + duration-*. Например в коде <span class="block px-6 py-3 transition-opacity duration-300 hover:opacity-0">Learn More</span> подразумевается, что transition-opacity изменяет именно свойство opacity с помощью анимации типа transition. При наведении hover:opacity-0 уменьшает непрозрачность до 0 за 300мс, за что отвечает класс duration-300.
Borders & Shadow
|
1 |
<div class="border rounded-lg shadow-md"> |
Классы:
rounded, rounded-xl- классы для скругления рамок;border-2- размер рамок, цвет рамок, стиль рамок;shadow, shadow-lg- классы для создания теней;text-shadow-md- классы для текстовых теней;opacity-25- классы для создания полупрозрачности.
Адаптивность (Responsive)
Tailwind CSS использует mobile-first подход.
|
1 |
<div class="text-sm md:text-lg lg:text-xl"> |
Брейкпоинты по умолчанию:
| Prefix | Размер |
|---|---|
| sm | 640px |
| md | 768px |
| lg | 1024px |
| xl | 1280px |
В примере ниже у нас есть 6 карточек в ряд на экране компьютера и на мобильном: 1 начальная карточка + 2 карточки в 2 ряда + 1 карточка замыкающая. Для того чтобы увидеть мобильную версию, откройте дополнительно вкладку HTML.
See the Pen Tailwind CSS adaptive example by HTML-plus (@ambassador) on CodePen.
Div-контейнер для карточек
Это не контейнер для всего текста, только для 6 вложенных в него элементов-карточек. Он имеет следующий код:
|
1 |
<div class="grid grid-cols-4 gap-6 lg:grid-cols-6"> |
Здесь мы указываем, что будем использовать сетку (grid) из 4-х колонок, но в lg-версии (большой экран) таких колонок будет 6.
Карточки 1 и 6 (большая на mobile)
|
1 2 3 4 5 6 7 8 |
<div class="col-span-4 lg:col-span-1 bg-white p-6 rounded-xl shadow"> <h3 class="font-semibold text-2xl lg:text-lg mb-2"> Card 1 </h3> <p class="text-gray-600 text-sm"> First card </p> </div> |
В разметке есть такие моменты:
col-span-4→ занимает всю ширину (mobile)lg:col-span-1→ 1/6 на desktoptext-2xl→ больше только на mobilelg:text-lg→ выравниваем на desktoptext-red-700 lg:text-red-400→ цвет текст тоже изменяется с более темного на более светлый
Карточки 2–5 (обычные)
|
1 2 3 4 5 6 |
<div class="col-span-2 lg:col-span-1 bg-white p-6 rounded-xl shadow"> <h3 class="font-semibold text-lg mb-2"> Card 2 </h3> <p class="text-gray-600 text-sm">Middle card</p> </div> |
- На mobile:
col-span-2 + grid-cols-4→ получается 2 карточки в ряд (2 ряда по 2) - На desktop:
lg:col-span-1→ все в одну линию
Тот же пример можно разобрать на Flexbox-модели:
See the Pen Tailwind CSS adaptive grid example by HTML-plus (@ambassador) on CodePen.
Тут классы сложней за счет того, что в divе-контейнере присутствует класс gap-6: <div class="flex flex-wrap gap-6">. Поэтому во вложенных карточках нужно рассчитывать ширину с учетом этого расстояния, иначе карточки не поместятся в контейнер:
|
1 2 3 4 5 6 7 8 9 10 11 |
<div class="basis-full sm:basis-[calc(50%-0.75rem)] lg:basis-[calc(16.666%-1.25rem)] bg-white p-6 rounded-xl shadow"> <h3 class="font-semibold text-2xl lg:text-lg mb-2"> Card 1 </h3> <p class="text-gray-600 text-sm"> First card </p> </div> |
Класс basis-full → 100% ширины (mobile). А вот размер basis приходится делить на 6 на desktop: это 16.666% и еще отнимаем 1.25rem .
Откуда взялись 1.25rem?
- Каждый из gap-6 = 1.5rem
- Однако у нас на 1 gap меньше 6, т.к. 6 карточек → 5 промежутков (gaps)
- Поэтому на одну карточку приходится ≈ 1.5rem × 5 / 6 ≈ 1.25rem
По 2 карты в 2 ряда
|
1 2 3 4 5 6 7 |
<div class="basis-[calc(50%-0.75rem)] sm:basis-[calc(50%-0.75rem)] lg:basis-[calc(16.666%-1.25rem)] bg-white p-6 rounded-xl shadow"> <h3 class="font-semibold text-lg mb-2">Card 2</h3> <p class="text-gray-600 text-sm">Middle card</p> </div> |
Тут у нас на desktop с разными размерами экрана разные классы в зависимости от значения gap. А на mobile класс рассчитываем, какbasis-[calc(50%-0.75rem)], т.к. класс gap-6 дает нам отступ между колонками в 1.5rem. Нам же нужно, чтоб половина его ушла в одну карточки и половина - в другую.
Выглядит не очень понятно? Поэтому в таком варианте лучше либо grid-модель, либо Bootstrap.
Классы с gap-* в Tailwind CSS:
| Класс | Значение |
|---|---|
| gap-1 | 0.25rem (4px) |
| gap-2 | 0.5rem (8px) |
| gap-3 | 0.75rem (12px) |
| gap-4 | 1rem (16px) |
| gap-5 | 1.25rem (20px) |
| gap-6 | 1.5rem (24px) |
| gap-8 | 2rem (32px) |
Dark Mode - темная тема
Вы можете включить темный режим - Dark Mode - в настройках Tailwind CSS. Для этого для проектов на React, Angular и т.п. в файле tailwind.config.js должно быть указано darkMode: 'class'.
Для использования темной темы можно переопределить запросом:
|
1 2 |
@import "tailwindcss"; @custom-variant dark (&:where(.dark, .dark *)); |
Кроме того, можно задать настройки в файле tailwind.config.js, если он предусмотрен в проекте:
|
1 2 3 4 5 6 7 8 |
export default { darkMode: 'class', // важно! content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], theme: { extend: {}, }, plugins: [], } |
Здесь darkMode: 'class' = управляем темой сами (не зависит от системы пользователя)
Если мы говорим о настройках в HTML-файле без использования React, Next, Vue.js (например, тестовый вариант на codepen.io), то нам нужно тоже добавить настройку в виде строки darkMode: 'class' в tailwind.config:
|
1 2 3 |
tailwind.config = { darkMode: 'class', } |
Важно: это JavaScript-код.
Тут важно понять, что Tailwind CSS не переключает тему сам. Он реагирует на класс dark, который добавляется на родительский элемент — обычно <html> или <body>. В разметке это выглядит так.
HTML-код:
|
1 2 3 4 5 6 7 |
<html class="dark"> <body> <div class="bg-white dark:bg-black"> <!-- ... --> </div> </body> </html> |
После этого все классы dark:* начинают работать, например, здесь:
|
1 |
<div class="bg-white dark:bg-gray-400 text-black dark:text-white"> |
Пример:
See the Pen Tailwind CSS dark-light mode by HTML-plus (@ambassador) on CodePen.
Как читать классы dark: если в коде есть классы bg-white dark:bg-gray-400, то они означают следующее:
- по умолчанию →
bg-white - если есть
.dark→bg-gray-400
Можно легко сделать кнопку-переключатель светлой/темной темы, которая будет выполнять простой код при нажатии: html.classList.toggle('dark'). Пример:
See the Pen Tailwind CSS section dark-light mode by HTML-plus (@ambassador) on CodePen.
Частая ошибка новичков: писать <div class="dark:bg-gray-900">, но при этом не использовать <html class="dark">. В этом случае работать не будет.
Автоматический выбор темы
Можно задать настройку darkMode: 'media', но в этом случае оформление полностью будет зависеть от того, какую тему выбрал в настройках браузера пользователь. Управлять будет нельзя.
Ограничения значения darkMode: 'media'
Нельзя:
- сделать кнопку «переключить тему»
- сохранить выбор пользователя
- переопределить системную тему
Можно:
- использовать управление классами в виде
dark:* - комбинировать с
hover:,focus:и т.д. - писать один и тот же HTML
Пример:
See the Pen Tailwind CSS section dark-light mode by HTML-plus (@ambassador) on CodePen.
В браузере Chrome вы можете выбрать настройки темы в меню Внешний вид. В этом случае вид страницы с Tailwind CSS будет также меняться.
Плагин для VSCode
Кстати, вы можете скачать плагин IntelliSense для VS Code, чтобы вам было удобно добавлять классы Tailwind CSS, т.к. там присутствуют такие функции, как автозаполнение, подсветка и проверка синтаксиса.
