Основные концепции
Использование утилит для стилизации элементов при наведении, фокусе и других состояниях.
Каждый утилитарный класс в Tailwind может применяться условно, добавляя вариант в начало имени класса, который описывает условие, на которое вы хотите воздействовать.
Например, чтобы применить класс bg-sky-700
при наведении, используйте класс hover:bg-sky-700
:
Наведите курсор на эту кнопку, чтобы увидеть изменение цвета фона
<button class="bg-sky-500 hover:bg-sky-700 ...">Сохранить изменения</button>
При написании CSS традиционным способом одно имя класса делало бы разные вещи в зависимости от текущего состояния:
Традиционно одно и то же имя класса применяет разные стили при наведении
.btn-primary { background-color: #0ea5e9;}.btn-primary:hover { background-color: #0369a1;}
В Tailwind, вместо добавления стилей для состояния наведения к существующему классу, вы добавляете другой класс к элементу, который только что-то делает при наведении:
В Tailwind используются отдельные классы для состояния по умолчанию и состояния наведения
.bg-sky-500 { background-color: #0ea5e9;}.hover\:bg-sky-700:hover { background-color: #0369a1;}
Обратите внимание, как hover:bg-sky-700
только определяет стили для состояния :hover
? Он ничего не делает по умолчанию, но как только вы наводите курсор на элемент с этим классом, цвет фона изменится на sky-700
.
Это то, что мы имеем в виду, когда говорим, что утилитарный класс может применяться условно — используя варианты, вы можете точно контролировать, как ваш дизайн ведет себя в разных состояниях, никогда не покидая HTML.
Tailwind включает варианты практически для всего, что вам когда-либо понадобится, включая:
:hover
, :focus
, :first-child
и :required
::before
, ::after
, ::placeholder
и ::selection
prefers-reduced-motion
[dir="rtl"]
и [open]
& > *
и & *
Эти варианты даже можно комбинировать для нацеливания на более специфичные ситуации, например, изменение цвета фона в тёмном режиме, на среднем брейкпоинте, при наведении:
<button class="dark:md:hover:bg-fuchsia-600 ...">Сохранить изменения</button>
В этом руководстве вы узнаете о каждом доступном варианте в фреймворке, как использовать их с вашими собственными пользовательскими классами, и даже как создавать свои собственные.
Стилизуйте элементы при наведении, фокусе и активном состоянии, используя варианты hover
, focus
и active
:
Попробуйте взаимодействовать с этой кнопкой, чтобы увидеть состояния наведения, фокуса и активности
<button class="bg-violet-500 hover:bg-violet-600 focus:outline-2 focus:outline-offset-2 focus:outline-violet-500 active:bg-violet-700 ..."> Сохранить изменения</button>
Tailwind также включает варианты для других интерактивных состояний, таких как :visited
, :focus-within
, :focus-visible
и других.
См. справочник псевдоклассов для полного списка доступных вариантов псевдоклассов.
Стилизуйте элемент, когда он является первым или последним дочерним элементом, используя варианты first
и last
:
Кристен Рамос
kristen.ramos@example.com
Флойд Майлз
floyd.miles@example.com
Кортни Генри
courtney.henry@example.com
Тед Фокс
ted.fox@example.com
<ul role="list"> {#each people as person} <!-- Удаляем верхний/нижний отступ, когда первый/последний дочерний элемент --> <li class="flex py-4 first:pt-0 last:pb-0"> <img class="h-10 w-10 rounded-full" src={person.imageUrl} alt="" /> <div class="ml-3 overflow-hidden"> <p class="text-sm font-medium text-gray-900 dark:text-white">{person.name}</p> <p class="truncate text-sm text-gray-500 dark:text-gray-400">{person.email}</p> </div> </li> {/each}</ul>
Вы также можете стилизовать элемент, когда он является нечётным или чётным дочерним элементом, используя варианты odd
и even
:
Name | Имя | Title | |
---|---|---|---|
Jane Cooper | Regional Paradigm Technician | jane.cooper@example.com | |
Cody Fisher | Product Directives Officer | cody.fisher@example.com | |
Leonard Krasner | Старший дизайнер | leonard.krasner@example.com | |
Emily Selman | Вице-президент по аппаратному обеспечению | emily.selman@example.com | |
Anna Roberts | Директор по стратегии | anna.roberts@example.com |
<table> <!-- ... --> <tbody> {#each people as person} <!-- Используйте разные цвета фона для нечётных и чётных строк --> <tr class="odd:bg-white even:bg-gray-50 dark:odd:bg-gray-900/50 dark:even:bg-gray-950"> <td>{person.name}</td> <td>{person.title}</td> <td>{person.email}</td> </tr> {/each} </tbody></table>
Используйте варианты nth-*
и nth-last-*
для стилизации дочерних элементов на основе их позиции в списке:
<div class="nth-3:underline"> <!-- ... --></div><div class="nth-last-5:underline"> <!-- ... --></div><div class="nth-of-type-4:underline"> <!-- ... --></div><div class="nth-last-of-type-6:underline"> <!-- ... --></div>
Вы можете передать любое число по умолчанию, и использовать произвольные значения для более сложных выражений, таких как nth-[2n+1_of_li]
.
Tailwind также включает варианты для других структурных псевдоклассов, таких как :only-child
, :first-of-type
, :empty
и других.
См. справочник по псевдоклассам для полного списка доступных вариантов псевдоклассов.
Стилизуйте элементы форм в различных состояниях, используя варианты, такие как required
, invalid
и disabled
:
Try making the email address valid to see the styles change
<input type="text" value="tbone" disabled class="invalid:border-pink-500 invalid:text-pink-600 focus:border-sky-500 focus:outline focus:outline-sky-500 focus:invalid:border-pink-500 focus:invalid:outline-pink-500 disabled:border-gray-200 disabled:bg-gray-50 disabled:text-gray-500 disabled:shadow-none dark:disabled:border-gray-700 dark:disabled:bg-gray-800/20 ..."/>
Использование вариантов для подобных вещей может уменьшить количество условной логики в ваших шаблонах, позволяя использовать один и тот же набор классов независимо от того, в каком состоянии находится input, и позволяя браузеру применять правильные стили за вас.
Tailwind также включает варианты для других состояний форм, таких как :read-only
, :indeterminate
, :checked
и другие.
См. справочник псевдоклассов для полного списка доступных вариантов псевдоклассов.
Используйте вариант has-*
для стилизации элемента на основе состояния или содержимого его дочерних элементов:
<label class="has-checked:bg-indigo-50 has-checked:text-indigo-900 has-checked:ring-indigo-200 dark:has-checked:bg-indigo-950 dark:has-checked:text-indigo-200 dark:has-checked:ring-indigo-900 ..."> <svg fill="currentColor"> <!-- ... --> </svg> Google Pay <input type="radio" class="checked:border-indigo-500 ..." /></label>
Вы можете использовать has-*
с псевдоклассом, например, has-[:focus]
, для стилизации элемента на основе состояния его дочерних элементов. Вы также можете использовать селекторы элементов, такие как has-[img]
или has-[a]
, для стилизации элемента на основе содержимого его дочерних элементов.
Если вам нужно стилизовать элемент на основе дочерних элементов родительского элемента, вы можете пометить родителя классом group
и использовать вариант group-has-*
для стилизации целевого элемента:
Просто счастлив быть здесь.
Мультидисциплинарный дизайнер, работающий на пересечении искусства и технологий.
alex-reed.com
Перемещаю пиксели. Бросаю div'ы.
<div class="group ..."> <img src="..." /> <h4>Spencer Sharp</h4> <svg class="hidden group-has-[a]:block ..."><!-- ... --></svg> <p>Дизайнер продукта в <a href="...">planeteria.tech</a></p></div>
Если вам нужно стилизовать элемент на основе дочерних элементов соседнего элемента, вы можете пометить соседний элемент классом peer
и использовать вариант peer-has-*
для стилизации целевого элемента:
<div> <label class="peer ..."> <input type="checkbox" name="todo[1]" checked /> Создать список дел </label> <svg class="peer-has-checked:hidden ..."><!-- ... --></svg></div>
Используйте вариант not-
для стилизации элемента, когда условие не выполняется.
Это особенно мощно в сочетании с другими вариантами псевдоклассов, например, комбинируя not-focus:
с hover:
для применения стилей наведения только когда элемент не в фокусе:
Попробуйте сфокусироваться на кнопке, а затем навести на неё
<button class="bg-indigo-600 hover:not-focus:bg-indigo-700"> <!-- ... --></button>
Вы также можете комбинировать вариант not-
с вариантами медиа-запросов, такими как forced-colors
или supports
, для стилизации элемента только когда что-то в окружении пользователя не соответствует истине:
<div class="not-supports-[display:grid]:flex"> <!-- ... --></div>
Когда вам нужно стилизовать элемент на основе состояния какого-то родительского элемента, пометьте родителя классом group
и используйте варианты group-*
, такие как group-hover
, для стилизации целевого элемента:
Наведите курсор на карточку, чтобы увидеть изменение цвета обоих текстовых элементов
<a href="#" class="group ..."> <div> <svg class="stroke-sky-500 group-hover:stroke-white ..." fill="none" viewBox="0 0 24 24"> <!-- ... --> </svg> <h3 class="text-gray-900 group-hover:text-white ...">Новый проект</h3> </div> <p class="text-gray-500 group-hover:text-white ...">Создайте новый проект из различных начальных шаблонов.</p></a>
Этот паттерн работает с каждым вариантом псевдо-класса, например group-focus
, group-active
или даже group-odd
.
При вложении групп вы можете стилизовать что-то на основе состояния конкретной родительской группы, дав этой родительской группе уникальное имя группы с помощью класса group/{name}
, и включив это имя в варианты с помощью классов типа group-hover/{name}
:
<ul role="list"> {#each people as person} <li class="group/item ..."> <!-- ... --> <a class="group/edit invisible group-hover/item:visible ..." href="tel:{person.phone}"> <span class="group-hover/edit:text-gray-700 ...">Call</span> <svg class="group-hover/edit:translate-x-0.5 group-hover/edit:text-gray-500 ..."><!-- ... --></svg> </a> </li> {/each}</ul>
Группы можно называть как угодно, и их не нужно настраивать каким-либо образом — просто назовите ваши группы прямо в разметке, и Tailwind автоматически сгенерирует необходимый CSS.
Вы можете создавать одноразовые варианты group-*
на лету, предоставив свой собственный селектор как произвольное значение в квадратных скобках:
<div class="group is-published"> <div class="hidden group-[.is-published]:block"> Published </div></div>
Для более точного контроля вы можете использовать символ &
для обозначения того, где .group
должен оказаться в итоговом селекторе относительно селектора, который вы передаете:
<div class="group"> <div class="group-[:nth-of-type(3)_&]:block"> <!-- ... --> </div></div>
Вариант in-*
работает аналогично group
, но вам не нужно добавлять group
к родительскому элементу:
<div tabindex="0" class="group"> <div class="opacity-50 group-focus:opacity-100"><div tabindex="0"> <div class="opacity-50 in-focus:opacity-100"> <!-- ... --> </div></div>
Вариант in-*
реагирует на изменения состояния в любом родительском элементе, поэтому если вам нужен более точный контроль, вам придется использовать group
вместо этого.
Когда вам нужно стилизовать элемент на основе состояния соседнего элемента, пометьте соседний элемент классом peer
, и используйте варианты peer-*
, такие как peer-invalid
, для стилизации целевого элемента:
Попробуйте сделать email-адрес действительным, чтобы увидеть исчезновение предупреждения
<form> <label class="block"> <span class="...">Email</span> <input type="email" class="peer ..." /> <p class="invisible peer-invalid:visible ...">Пожалуйста, укажите действительный email-адрес.</p> </label></form>
Это позволяет делать всевозможные интересные трюки, например плавающие метки, без использования JavaScript.
Этот паттерн работает с каждым вариантом псевдо-класса, например peer-focus
, peer-required
и peer-disabled
.
Важно отметить, что маркер peer
может использоваться только на предыдущих соседних элементах из-за того, как работает комбинатор последующих соседних элементов в CSS:
Не будет работать, только предыдущие соседние элементы могут быть помечены как peers
<label> <span class="peer-invalid:text-red-500 ...">Email</span> <input type="email" class="peer ..." /></label>
При использовании нескольких peers вы можете стилизовать что-то на основе состояния конкретного peer, дав этому peer уникальное имя с помощью класса peer/{name}
, и включив это имя в варианты с помощью классов типа peer-checked/{name}
:
<fieldset> <legend>Статус публикации</legend> <input id="draft" class="peer/draft" type="radio" name="status" checked /> <label for="draft" class="peer-checked/draft:text-sky-500">Черновик</label> <input id="published" class="peer/published" type="radio" name="status" /> <label for="published" class="peer-checked/published:text-sky-500">Опубликовано</label> <div class="hidden peer-checked/draft:block">Черновики видны только администраторам.</div> <div class="hidden peer-checked/published:block">Ваша запись будет публично видна на вашем сайте.</div></fieldset>
Peers могут быть названы как угодно и не требуют никакой настройки — просто назовите ваших peers прямо в разметке, и Tailwind автоматически сгенерирует необходимый CSS.
Вы можете создавать одноразовые варианты peer-*
на лету, предоставляя свой собственный селектор как произвольное значение в квадратных скобках:
<form> <label for="email">Email:</label> <input id="email" name="email" type="email" class="is-dirty peer" required /> <div class="peer-[.is-dirty]:peer-required:block hidden">Это поле обязательно для заполнения.</div> <!-- ... --></form>
Для большего контроля вы можете использовать символ &
, чтобы обозначить, где .peer
должен оказаться в финальном селекторе относительно селектора, который вы передаете:
<div> <input type="text" class="peer" /> <div class="hidden peer-[:nth-of-type(3)_&]:block"> <!-- ... --> </div></div>
Стилизуйте псевдоэлементы ::before
и ::after
с помощью вариантов before
и after
:
<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>
При использовании этих вариантов Tailwind автоматически добавляет content: ''
по умолчанию, поэтому вам не нужно указывать его, если только вы не хотите другое значение:
Когда вы выглядите annoyed all the time, people think that you're busy.
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic dark:text-white"> When you look <span class="relative inline-block before:absolute before:-inset-1 before:block before:-skew-y-3 before:bg-pink-500"> <span class="relative text-white dark:text-gray-950">annoyed</span> </span> all the time, people think that you're busy.</blockquote>
Стоит отметить, что в большинстве случаев в проектах Tailwind вам не нужны псевдоэлементы ::before
и ::after
— обычно проще использовать реальный HTML элемент.
Например, вот тот же дизайн сверху, но использующий <span>
вместо псевдоэлемента ::before
, что немного легче читается и фактически содержит меньше кода:
<blockquote class="text-center text-2xl font-semibold text-gray-900 italic"> When you look <span class="relative"> <span class="absolute -inset-1 block -skew-y-3 bg-pink-500" aria-hidden="true"></span> <span class="relative text-white">annoyed</span> </span> all the time, people think that you're busy.</blockquote>
Сохраните before
и after
для ситуаций, когда важно, чтобы содержимое псевдоэлемента фактически не находилось в DOM и не могло быть выбрано пользователем.
Стилизуйте текст-заполнитель любого input или textarea с помощью варианта placeholder
:
<input class="placeholder:text-gray-500 placeholder:italic ..." placeholder="Search for anything..." type="text" name="search"/>
Стилизуйте кнопку в file inputs с помощью варианта file
:
<input type="file" class="file:mr-4 file:rounded-full file:border-0 file:bg-violet-50 file:px-4 file:py-2 file:text-sm file:font-semibold file:text-violet-700 hover:file:bg-violet-100 dark:file:bg-violet-600 dark:file:text-violet-100 dark:hover:file:bg-violet-500 ..."/>
Стилизуйте счетчики или маркеры в списках с помощью варианта marker
:
<ul role="list" class="list-disc marker:text-sky-400 ..."> <li>5 cups chopped Porcini mushrooms</li> <li>1/2 cup of olive oil</li> <li>3lb of celery</li></ul>
Мы разработали вариант marker
так, чтобы он был наследуемым, поэтому хотя вы можете использовать его напрямую на элементе <li>
, вы также можете использовать его на родительском элементе, чтобы избежать повторений.
Стилизуйте активное выделение текста с помощью варианта selection
:
Попробуйте выделить часть этого текста мышью
Так я начал заходить в воду. Не буду врать вам, ребята, я был в ужасе. Но я продолжал идти, и когда я прошел мимо волн, на меня снизошло странное спокойствие. Не знаю, было ли это божественное вмешательство или родство всех живых существ, но говорю вам, Джерри, в тот момент я был морским биологом.
<div class="selection:bg-fuchsia-300 selection:text-fuchsia-900"> <p> Так я начал заходить в воду. Не буду врать вам, ребята, я был в ужасе. Но я продолжал идти, и когда я прошел мимо волн, на меня снизошло странное спокойствие. Не знаю, было ли это божественное вмешательство или родство всех живых существ, но говорю вам, Джерри, в тот момент я <em>был</em> морским биологом. </p></div>
Мы разработали вариант selection
так, чтобы он был наследуемым, поэтому вы можете добавить его в любое место в дереве, и он будет применен ко всем дочерним элементам.
Это позволяет легко установить цвет выделения в соответствии с вашим брендом по всему сайту:
<html> <head> <!-- ... --> </head> <body class="selection:bg-pink-300"> <!-- ... --> </body></html>
Стилизуйте первую строку в блоке содержимого с помощью варианта first-line
, и первую букву с помощью варианта first-letter
:
Well, let me tell you something, funny boy. Y'know that little stamp, the one that says "New York Public Library"? Well that may not mean anything to you, but that means a lot to me. One whole hell of a lot.
Sure, go ahead, laugh if you want to. I've seen your type before: Flashy, making the scene, flaunting convention. Yeah, I know what you're thinking. What's this guy making such a big stink about old library books? Well, let me give you a hint, junior.
<div class="text-gray-700"> <p class="first-letter:float-left first-letter:mr-3 first-letter:text-7xl first-letter:font-bold first-letter:text-gray-900 first-line:tracking-widest first-line:uppercase" > Well, let me tell you something, funny boy. Y'know that little stamp, the one that says "New York Public Library"? </p> <p class="mt-6">Well that may not mean anything to you, but that means a lot to me. One whole hell of a lot.</p></div>
Стилизуйте фон нативного элемента <dialog>
с помощью варианта backdrop
:
<dialog class="backdrop:bg-gray-50"> <form method="dialog"> <!-- ... --> </form></dialog>
If you're using native <dialog>
elements in your project, you may also want to read about styling open/closed states using the open
variant.
Для стилизации элемента на определённой контрольной точке используйте адаптивные варианты, такие как md
и lg
.
Например, это будет отображать сетку из 3 колонок на мобильных устройствах, сетку из 4 колонок на экранах средней ширины и сетку из 6 колонок на широких экранах:
<div class="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6"> <!-- ... --></div>
Для стилизации элемента на основе ширины родительского элемента вместо viewport используйте варианты, такие как @md
и @lg
:
<div class="@container"> <div class="flex flex-col @md:flex-row"> <!-- ... --> </div></div>
Ознакомьтесь с документацией Адаптивный дизайн для подробного изучения того, как работают эти функции.
Медиа-запрос prefers-color-scheme
сообщает вам, предпочитает ли пользователь светлую или тёмную тему, и обычно настраивается на уровне операционной системы.
Используйте утилиты без варианта для нацеливания на светлый режим, и используйте вариант dark
для предоставления переопределений для тёмного режима:
Светлый режим
Ручка Zero Gravity может использоваться для письма в любой ориентации, включая вверх ногами. Она даже работает в открытом космосе.
Тёмный режим
The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.
<div class="bg-white dark:bg-gray-900 ..."> <!-- ... --> <h3 class="text-gray-900 dark:text-white ...">Writes upside-down</h3> <p class="text-gray-500 dark:text-gray-400 ..."> The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space. </p></div>
Ознакомьтесь с документацией Тёмный режим для подробного изучения того, как работает эта функция.
Медиа-запрос prefers-reduced-motion
сообщает вам, запросил ли пользователь минимизацию несущественных анимаций.
Используйте вариант motion-reduce
для условного добавления стилей, когда пользователь запросил уменьшение анимации:
Попробуйте эмулировать `prefers-reduced-motion: reduce` в инструментах разработчика, чтобы скрыть спиннер
<button type="button" class="bg-indigo-500 ..." disabled> <svg class="animate-spin motion-reduce:hidden ..." viewBox="0 0 24 24"><!-- ... --></svg> Processing...</button>
Tailwind также включает вариант motion-safe
, который добавляет стили только когда пользователь не запросил уменьшение анимации. Это может быть полезно, когда использование помощника motion-reduce
означало бы необходимость "отменять" много стилей:
<!-- Using `motion-reduce` can mean lots of "undoing" styles --><button class="transition hover:-translate-y-0.5 motion-reduce:transition-none motion-reduce:hover:translate-y-0 ..."> Save changes</button><!-- Using `motion-safe` is less code in these situations --><button class="motion-safe:transition motion-safe:hover:-translate-x-0.5 ...">Save changes</button>
Медиа-запрос prefers-contrast
сообщает вам, запросил ли пользователь больше или меньше контраста.
Используйте вариант contrast-more
для условного добавления стилей, когда пользователь запросил больше контраста:
Попробуйте эмулировать `prefers-contrast: more` в инструментах разработчика, чтобы увидеть изменения
<label class="block"> <span class="block text-sm font-medium text-gray-700">Social Security Number</span> <input class="border-gray-200 placeholder-gray-400 contrast-more:border-gray-400 contrast-more:placeholder-gray-500 ..." /> <p class="text-gray-600 opacity-10 contrast-more:opacity-100 ...">We need this to steal your identity.</p></label>
Tailwind также включает вариант contrast-less
, который вы можете использовать для условного добавления стилей, когда пользователь запросил меньше контраста.
Медиа-запрос forced-colors
указывает, использует ли пользователь режим принудительных цветов. Эти режимы переопределяют цвета вашего сайта пользовательской палитрой для текста, фонов, ссылок и кнопок.
Используйте вариант forced-colors
для условного добавления стилей, когда пользователь включил режим принудительных цветов:
Попробуйте эмулировать `forced-colors: active` в инструментах разработчика, чтобы увидеть изменения
<label> <input type="radio" class="appearance-none forced-colors:appearance-auto" /> <p class="hidden forced-colors:block">Cyan</p> <div class="bg-cyan-200 forced-colors:hidden ..."></div> <div class="bg-cyan-500 forced-colors:hidden ..."></div></label>
Используйте вариант not-forced-colors
для применения стилей, когда пользователь не использует режим принудительных цветов:
<div class="not-forced-colors:appearance-none ..."> <!-- ... --></div>
Tailwind также включает утилиты forced color adjust для включения и отключения принудительных цветов.
Используйте вариант inverted-colors
для условного добавления стилей, когда пользователь включил инвертированную цветовую схему:
<div class="shadow-xl inverted-colors:shadow-none ..."> <!-- ... --></div>
Медиа-запрос pointer
сообщает вам, есть ли у пользователя основное указывающее устройство, такое как мышь, и точность этого указывающего устройства.
Используйте вариант pointer-fine
для нацеливания на точное указывающее устройство, такое как мышь или трекпад, или вариант pointer-coarse
для нацеливания на менее точное указывающее устройство, такое как сенсорный экран, что может быть полезно для предоставления больших целей для клика на сенсорных устройствах:
Попробуйте эмулировать сенсорное устройство в инструментах разработчика, чтобы увидеть изменения
<fieldset aria-label="Выберите опцию памяти"> <div class="flex items-center justify-between"> <div>RAM</div> <a href="#"> См. спецификации производительности </a> </div> <div class="mt-4 grid grid-cols-6 gap-2 pointer-coarse:mt-6 pointer-coarse:grid-cols-3 pointer-coarse:gap-4"> <label class="p-2 pointer-coarse:p-4 ..."> <input type="radio" name="memory-option" value="4 GB" className="sr-only" /> <span>4 GB</span> </label> <!-- ... --> </div></fieldset>
В то время как pointer
нацелен только на основное указывающее устройство, any-pointer
используется для нацеливания на любое из доступных указывающих устройств. Используйте варианты any-pointer-fine
и any-pointer-coarse
для предоставления различных стилей, если хотя бы одно подключенное указывающее устройство соответствует критериям.
Вы можете использовать pointer-none
и any-pointer-none
для нацеливания на отсутствие указывающего устройства.
Используйте варианты portrait
и landscape
для условного добавления стилей, когда область просмотра находится в определенной ориентации:
<div> <div class="portrait:hidden"> <!-- ... --> </div> <div class="landscape:hidden"> <p>Этот опыт предназначен для просмотра в альбомной ориентации. Пожалуйста, поверните ваше устройство для просмотра сайта.</p> </div></div>
Используйте вариант noscript
для условного добавления стилей в зависимости от того, включен ли у пользователя скриптинг, такой как JavaScript:
<div class="hidden noscript:block"> <p>Этот опыт требует JavaScript для работы. Пожалуйста, включите JavaScript в настройках вашего браузера.</p></div>
Используйте вариант print
для условного добавления стилей, которые применяются только при печати документа:
<div> <article class="print:hidden"> <h1>Мой секретный рецепт пиццы</h1> <p>Этот рецепт секретный и не должен быть передан никому</p> <!-- ... --> </article> <div class="hidden print:block">Вы серьёзно пытаетесь распечатать это? Это секрет!</div></div>
Используйте вариант supports-[...]
для стилизации элементов в зависимости от того, поддерживается ли определенная функция в браузере пользователя:
<div class="flex supports-[display:grid]:grid ..."> <!-- ... --></div>
Под капотом вариант supports-[...]
генерирует @supports правила
и принимает все, что вы бы использовали с @supports (...)
между квадратными скобками, например пару свойство/значение, и даже выражения с использованием and
и or
.
Для краткости, если вам нужно только проверить, поддерживается ли свойство (а не конкретное значение), вы можете просто указать имя свойства:
<div class="bg-black/75 supports-backdrop-filter:bg-black/25 supports-backdrop-filter:backdrop-blur ..."> <!-- ... --></div>
Используйте вариант not-supports-[...]
для стилизации элементов в зависимости от того, не поддерживается ли определенная функция в браузере пользователя:
<div class="not-supports-[display:grid]:flex"> <!-- ... --></div>
Вы можете настроить сокращения для часто используемых правил @supports
в вашем проекте, создав новый вариант в пространстве имен supports-*
:
@custom-variant supports-grid { @supports (display: grid) { @slot; }}
Затем вы можете использовать эти пользовательские варианты supports-*
в вашем проекте:
<div class="supports-grid:grid"> <!-- ... --></div>
Используйте вариант starting
для установки внешнего вида элемента при его первом рендеринге в DOM или при переходе из display: none
в видимое состояние:
<div> <button popovertarget="my-popover">Проверить обновления</button> <div popover id="my-popover" class="opacity-0 starting:open:opacity-0 ..."> <!-- ... --> </div></div>
Используйте вариант aria-*
для условного стилизования элементов на основе ARIA атрибутов.
Например, чтобы применить класс bg-sky-700
когда атрибут aria-checked
установлен в true
, используйте класс aria-checked:bg-sky-700
:
<div aria-checked="true" class="bg-gray-600 aria-checked:bg-sky-700"> <!-- ... --></div>
По умолчанию мы включили варианты для наиболее распространенных булевых ARIA атрибутов:
Variant | CSS |
---|---|
aria-busy | &[aria-busy="true"] |
aria-checked | &[aria-checked="true"] |
aria-disabled | &[aria-disabled="true"] |
aria-expanded | &[aria-expanded="true"] |
aria-hidden | &[aria-hidden="true"] |
aria-pressed | &[aria-pressed="true"] |
aria-readonly | &[aria-readonly="true"] |
aria-required | &[aria-required="true"] |
aria-selected | &[aria-selected="true"] |
Вы можете настроить, какие варианты aria-*
доступны, создав новый вариант:
@custom-variant aria-asc (&[aria-sort="ascending"]);@custom-variant aria-desc (&[aria-sort="descending"]);
Если вам нужно использовать одноразовый вариант aria
, который не имеет смысла включать в ваш проект, или для более сложных ARIA-атрибутов, которые принимают конкретные значения, используйте квадратные скобки для генерации свойства на лету с помощью любого произвольного значения:
Номер счёта | Клиент | Сумма |
---|---|---|
#100 | Pendant Publishing | $2,000.00 |
#101 | Kruger Industrial Smoothing | $545.00 |
#102 | J. Peterman | $10,000.25 |
<table> <thead> <tr> <th aria-sort="ascending" class="aria-[sort=ascending]:bg-[url('/img/down-arrow.svg')] aria-[sort=descending]:bg-[url('/img/up-arrow.svg')]" > Номер счёта </th> <!-- ... --> </tr> </thead> <!-- ... --></table>
Варианты состояний ARIA также могут нацеливаться на родительские и соседние элементы с помощью вариантов group-aria-*
и peer-aria-*
:
<table> <thead> <tr> <th aria-sort="ascending" class="group"> Номер счёта <svg class="group-aria-[sort=ascending]:rotate-0 group-aria-[sort=descending]:rotate-180"><!-- ... --></svg> </th> <!-- ... --> </tr> </thead> <!-- ... --></table>
Используйте вариант data-*
для условного применения стилей на основе data attributes.
Чтобы проверить, существует ли data-атрибут (а не конкретное значение), вы можете просто указать имя атрибута:
<!-- Will apply --><div data-active class="border border-gray-300 data-active:border-purple-500"> <!-- ... --></div><!-- Will not apply --><div class="border border-gray-300 data-active:border-purple-500"> <!-- ... --></div>
If you need to check for a specific value you may use an arbitrary value:
<!-- Will apply --><div data-size="large" class="data-[size=large]:p-8"> <!-- ... --></div><!-- Will not apply --><div data-size="medium" class="data-[size=large]:p-8"> <!-- ... --></div>
Альтернативно, вы можете настроить сокращения для часто используемых data-атрибутов в вашем проекте, создав новый вариант в пространстве имен data-*
:
@import "tailwindcss";@custom-variant data-checked (&[data-ui~="checked"]);
Затем вы можете использовать эти пользовательские варианты data-*
в вашем проекте:
<div data-ui="checked active" class="data-checked:underline"> <!-- ... --></div>
Используйте варианты rtl
и ltr
для условного добавления стилей в режимах справа-налево и слева-направо соответственно при создании многонаправленных макетов:
Left-to-right
Tom Cook
Директор по операциям
Right-to-left
تامر كرم
الرئيس التنفيذي
<div class="group flex items-center"> <img class="h-12 w-12 shrink-0 rounded-full" src="..." alt="" /> <div class="ltr:ml-3 rtl:mr-3"> <p class="text-gray-700 group-hover:text-gray-900 ...">...</p> <p class="text-gray-500 group-hover:text-gray-700 ...">...</p> </div></div>
Помните, что эти варианты полезны только если вы создаете сайт, который должен поддерживать оба направления — слева направо и справа налево. Если вы создаете сайт, который должен поддерживать только одно направление, вам не нужны эти варианты — просто применяйте стили, которые подходят для вашего контента.
Используйте вариант open
для условного добавления стилей, когда элемент <details>
или <dialog>
находится в открытом состоянии:
Попробуйте переключить раскрывающийся элемент, чтобы увидеть изменение стилей
The mug is round. The jar is round. They should call it Roundtine.
<details class="border border-transparent open:border-black/10 open:bg-gray-100 ..." open> <summary class="text-sm leading-6 font-semibold text-gray-900 select-none">Why do they call it Ovaltine?</summary> <div class="mt-3 text-sm leading-6 text-gray-600"> <p>The mug is round. The jar is round. They should call it Roundtine.</p> </div></details>
Этот вариант также нацелен на псевдо-класс :popover-open
для попапов:
<div> <button popovertarget="my-popover">Open Popover</button> <div popover id="my-popover" class="opacity-0 open:opacity-100 ..."> <!-- ... --> </div></div>
Вариант inert
позволяет стилизовать элементы, помеченные атрибутом inert
:
<form> <legend>Notification preferences</legend> <fieldset> <input type="radio" /> <label> Custom </label> <fieldset inert class="inert:opacity-50"> <!-- ... --> </fieldset> <input type="radio" /> <label> Everything </label> </fieldset></form>
Это полезно для добавления визуальных подсказок, которые делают очевидным, что разделы контента не являются интерактивными.
Хотя обычно предпочтительнее размещать утилитарные классы непосредственно на дочерних элементах, вы можете использовать вариант *
в ситуациях, когда вам нужно стилизовать прямые дочерние элементы, которыми вы не можете управлять:
<div> <h2>Categories<h2> <ul class="*:rounded-full *:border *:border-sky-100 *:bg-sky-50 *:px-2 *:py-0.5 dark:text-sky-300 dark:*:border-sky-500/15 dark:*:bg-sky-500/10 ..."> <li>Sales</li> <li>Marketing</li> <li>SEO</li> <!-- ... --> </ul></div>
Важно отметить, что переопределение стиля с помощью утилиты непосредственно на дочернем элементе не будет работать, поскольку правила для дочерних элементов генерируются после обычных правил и имеют ту же специфичность:
Не будет работать, дочерние элементы не могут переопределить стили, заданные им родителем.
<ul class="*:bg-sky-50 ..."> <li class="bg-red-50 ...">Sales</li> <li>Marketing</li> <li>SEO</li> <!-- ... --></ul>
Как и *
, вариант **
можно использовать для стилизации дочерних элементов. Основное различие заключается в том, что **
будет применять стили ко всем потомкам, а не только к прямым дочерним элементам. Это особенно полезно, когда вы комбинируете его с другим вариантом для сужения того, что вы выбираете:
<ul class="**:data-avatar:size-12 **:data-avatar:rounded-full ..."> {#each items as item} <li> <img src={item.src} data-avatar /> <p>{item.name}</p> </li> {/each}</ul>
Так же, как произвольные значения позволяют использовать пользовательские значения с вашими утилитарными классами, произвольные варианты позволяют писать пользовательские варианты селекторов прямо в HTML.
Произвольные варианты — это просто строки формата, которые представляют селектор, обёрнутые в квадратные скобки. Например, этот произвольный вариант изменяет курсор на grabbing
, когда элемент имеет класс is-dragging
:
<ul role="list"> {#each items as item} <li class="[&.is-dragging]:cursor-grabbing">{item}</li> {/each}</ul>
Произвольные варианты можно комбинировать со встроенными вариантами или друг с другом, точно так же, как и остальные варианты в Tailwind:
<ul role="list"> {#each items as item} <li class="[&.is-dragging]:active:cursor-grabbing">{item}</li> {/each}</ul>
Если в вашем селекторе нужны пробелы, вы можете использовать подчеркивание. Например, этот произвольный вариант выбирает все элементы p
внутри элемента, к которому вы добавили класс:
<div class="[&_p]:mt-4"> <p>Lorem ipsum...</p> <ul> <li> <p>Lorem ipsum...</p> </li> <!-- ... --> </ul></div>
Вы также можете использовать at-правила, такие как @media
или @supports
, в произвольных вариантах:
<div class="flex [@supports(display:grid)]:grid"> <!-- ... --></div>
При использовании произвольных вариантов с at-правилами заполнитель &
не нужен, точно так же, как при вложении с препроцессором.
Если вы обнаруживаете, что используете один и тот же произвольный вариант несколько раз в своем проекте, возможно, стоит создать пользовательский вариант с помощью директивы @custom-variant
:
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
Теперь вы можете использовать вариант theme-midnight:<utility>
в вашем HTML:
<html data-theme="midnight"> <button class="theme-midnight:bg-black ..."></button></html>
Узнайте больше о добавлении пользовательских вариантов в документации по добавлению пользовательских стилей.
Таблица быстрой справки всех вариантов, включенных в Tailwind по умолчанию.
Variant | CSS |
---|---|
hover | @media (hover: hover) { &:hover } |
focus | &:focus |
focus-within | &:focus-within |
focus-visible | &:focus-visible |
active | &:active |
visited | &:visited |
target | &:target |
* | :is(& > *) |
** | :is(& *) |
has-[...] | &:has(...) |
group-[...] | &:is(:where(.group)... *) |
peer-[...] | &:is(:where(.peer)... ~ *) |
in-[...] | :where(...) & |
not-[...] | &:not(...) |
inert | &:is([inert], [inert] *) |
first | &:first-child |
last | &:last-child |
only | &:only-child |
odd | &:nth-child(odd) |
even | &:nth-child(even) |
first-of-type | &:first-of-type |
last-of-type | &:last-of-type |
only-of-type | &:only-of-type |
nth-[...] | &:nth-child(...) |
nth-last-[...] | &:nth-last-child(...) |
nth-of-type-[...] | &:nth-of-type(...) |
nth-last-of-type-[...] | &:nth-last-of-type(...) |
empty | &:empty |
disabled | &:disabled |
enabled | &:enabled |
checked | &:checked |
indeterminate | &:indeterminate |
default | &:default |
optional | &:optional |
required | &:required |
valid | &:valid |
invalid | &:invalid |
user-valid | &:user-valid |
user-invalid | &:user-invalid |
in-range | &:in-range |
out-of-range | &:out-of-range |
placeholder-shown | &:placeholder-shown |
details-content | &:details-content |
autofill | &:autofill |
read-only | &:read-only |
before | &::before |
after | &::after |
first-letter | &::first-letter |
first-line | &::first-line |
marker | &::marker, & *::marker |
selection | &::selection |
file | &::file-selector-button |
backdrop | &::backdrop |
placeholder | &::placeholder |
sm | @media (width >= 40rem) |
md | @media (width >= 48rem) |
lg | @media (width >= 64rem) |
xl | @media (width >= 80rem) |
2xl | @media (width >= 96rem) |
min-[...] | @media (width >= ...) |
max-sm | @media (width < 40rem) |
max-md | @media (width < 48rem) |
max-lg | @media (width < 64rem) |
max-xl | @media (width < 80rem) |
max-2xl | @media (width < 96rem) |
max-[...] | @media (width < ...) |
@3xs | @container (width >= 16rem) |
@2xs | @container (width >= 18rem) |
@xs | @container (width >= 20rem) |
@sm | @container (width >= 24rem) |
@md | @container (width >= 28rem) |
@lg | @container (width >= 32rem) |
@xl | @container (width >= 36rem) |
@2xl | @container (width >= 42rem) |
@3xl | @container (width >= 48rem) |
@4xl | @container (width >= 56rem) |
@5xl | @container (width >= 64rem) |
@6xl | @container (width >= 72rem) |
@7xl | @container (width >= 80rem) |
@min-[...] | @container (width >= ...) |
@max-3xs | @container (width < 16rem) |
@max-2xs | @container (width < 18rem) |
@max-xs | @container (width < 20rem) |
@max-sm | @container (width < 24rem) |
@max-md | @container (width < 28rem) |
@max-lg | @container (width < 32rem) |
@max-xl | @container (width < 36rem) |
@max-2xl | @container (width < 42rem) |
@max-3xl | @container (width < 48rem) |
@max-4xl | @container (width < 56rem) |
@max-5xl | @container (width < 64rem) |
@max-6xl | @container (width < 72rem) |
@max-7xl | @container (width < 80rem) |
@max-[...] | @container (width < ...) |
dark | @media (prefers-color-scheme: dark) |
motion-safe | @media (prefers-reduced-motion: no-preference) |
motion-reduce | @media (prefers-reduced-motion: reduce) |
contrast-more | @media (prefers-contrast: more) |
contrast-less | @media (prefers-contrast: less) |
forced-colors | @media (forced-colors: active) |
inverted-colors | @media (inverted-colors: inverted) |
pointer-fine | @media (pointer: fine) |
pointer-coarse | @media (pointer: coarse) |
pointer-none | @media (pointer: none) |
any-pointer-fine | @media (any-pointer: fine) |
any-pointer-coarse | @media (any-pointer: coarse) |
any-pointer-none | @media (any-pointer: none) |
portrait | @media (orientation: portrait) |
landscape | @media (orientation: landscape) |
noscript | @media (scripting: none) |
@media print | |
supports-[…] | @supports (…) |
aria-busy | &[aria-busy="true"] |
aria-checked | &[aria-checked="true"] |
aria-disabled | &[aria-disabled="true"] |
aria-expanded | &[aria-expanded="true"] |
aria-hidden | &[aria-hidden="true"] |
aria-pressed | &[aria-pressed="true"] |
aria-readonly | &[aria-readonly="true"] |
aria-required | &[aria-required="true"] |
aria-selected | &[aria-selected="true"] |
aria-[…] | &[aria-…] |
data-[…] | &[data-…] |
rtl | &:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) |
ltr | &:where(:dir(ltr), [dir="ltr"], [dir="ltr"] *) |
open | &:is([open], :popover-open, :open) |
starting | @starting-style |
Это полный список примеров для всех вариантов псевдоклассов, включенных в Tailwind, чтобы дополнить документацию по псевдоклассам в начале этого руководства.
Стилизуйте элемент, когда пользователь наводит на него курсор мыши, используя вариант hover
:
<div class="bg-black hover:bg-white ..."> <!-- ... --></div>
Стилизуйте элемент, когда он имеет фокус, используя вариант focus
:
<input class="border-gray-300 focus:border-blue-400 ..." />
Стилизуйте элемент, когда он или один из его потомков имеет фокус, используя вариант focus-within
:
<div class="focus-within:shadow-lg ..."> <input type="text" /></div>
Style an element when it has been focused using the keyboard using the focus-visible
variant:
<button class="focus-visible:outline-2 ...">Submit</button>
Стилизуйте элемент, когда он нажимается, используя вариант active
:
<button class="bg-blue-500 active:bg-blue-600 ...">Submit</button>
Стилизуйте ссылку, когда она уже была посещена, используя вариант visited
:
<a href="https://seinfeldquotes.com" class="text-blue-600 visited:text-purple-600 ..."> Inspiration </a>
Стилизуйте элемент, если его ID соответствует текущему фрагменту URL, используя вариант target
:
<div id="about" class="target:shadow-lg ..."> <!-- ... --></div>
Стилизуйте элемент, если он является первым дочерним элементом, используя вариант first
:
<ul> {#each people as person} <li class="py-4 first:pt-0 ..."> <!-- ... --> </li> {/each}</ul>
Стилизуйте элемент, если он является последним дочерним элементом, используя вариант last
:
<ul> {#each people as person} <li class="py-4 last:pb-0 ..."> <!-- ... --> </li> {/each}</ul>
Стилизуйте элемент, если он является единственным дочерним элементом, используя вариант only
:
<ul> {#each people as person} <li class="py-4 only:py-0 ..."> <!-- ... --> </li> {/each}</ul>
Стилизуйте элемент, если он является нечётным по номеру дочерним элементом, используя вариант odd
:
<table> {#each people as person} <tr class="bg-white odd:bg-gray-100 ..."> <!-- ... --> </tr> {/each}</table>
Стилизуйте элемент, если он является чётным по номеру дочерним элементом, используя вариант even
:
<table> {#each people as person} <tr class="bg-white even:bg-gray-100 ..."> <!-- ... --> </tr> {/each}</table>
Стилизуйте элемент, если он является первым дочерним элементом своего типа, используя вариант first-of-type
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="ml-2 first-of-type:ml-6 ..."> <!-- ... --> </a> {/each}</nav>
Стилизуйте элемент, если он является последним дочерним элементом своего типа, используя вариант last-of-type
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mr-2 last-of-type:mr-6 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Стилизуйте элемент, если он является единственным дочерним элементом своего типа, используя вариант only-of-type
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 only-of-type:mx-6 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Стилизуйте элемент в определённой позиции, используя вариант nth
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-3:mx-6 nth-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Стилизуйте элемент в определённой позиции с конца, используя вариант nth-last
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-last-3:mx-6 nth-last-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Стилизуйте элемент в определённой позиции того же типа, используя вариант nth-of-type
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-of-type-3:mx-6 nth-of-type-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Стилизуйте элемент в определённой позиции с конца того же типа, используя вариант nth-last-of-type
:
<nav> <img src="/logo.svg" alt="Vandelay Industries" /> {#each links as link} <a href="#" class="mx-2 nth-last-of-type-3:mx-6 nth-last-of-type-[3n+1]:mx-7 ..."> <!-- ... --> </a> {/each} <button>More</button></nav>
Стилизуйте элемент, если у него нет содержимого, используя вариант empty
:
<ul> {#each people as person} <li class="empty:hidden ...">{person.hobby}</li> {/each}</ul>
Стилизуйте поле ввода, когда оно отключено, используя вариант disabled
:
<input class="disabled:opacity-75 ..." />
Стилизуйте поле ввода, когда оно включено, используя вариант enabled
, что особенно полезно, когда вы хотите применить другой стиль только когда элемент не отключен:
<input class="enabled:hover:border-gray-400 disabled:opacity-75 ..." />
Стилизуйте флажок или переключатель, когда он отмечен, используя вариант checked
:
<input type="checkbox" class="appearance-none checked:bg-blue-500 ..." />
Стилизуйте флажок или переключатель в неопределенном состоянии, используя вариант indeterminate
:
<input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />
Стилизуйте опцию, флажок или переключатель, который был значением по умолчанию при первоначальной загрузке страницы, используя вариант default
:
<input type="checkbox" class="default:outline-2 ..." />
Стилизуйте поле ввода, когда оно необязательно, используя вариант optional
:
<input class="border optional:border-red-500 ..." />
Стилизуйте поле ввода, когда оно обязательно, используя вариант required
:
<input required class="border required:border-red-500 ..." />
Стилизуйте поле ввода, когда оно валидно, используя вариант valid
:
<input required class="border valid:border-green-500 ..." />
Стилизуйте поле ввода, когда оно невалидно, используя вариант invalid
:
<input required class="border invalid:border-red-500 ..." />
Стилизуйте поле ввода, когда оно валидно и пользователь взаимодействовал с ним, используя вариант user-valid
:
<input required class="border user-valid:border-green-500" />
Стилизуйте поле ввода, когда оно невалидно и пользователь взаимодействовал с ним, используя вариант user-invalid
:
<input required class="border user-invalid:border-red-500" />
Стилизуйте поле ввода, когда его значение находится в пределах указанного диапазона, используя вариант in-range
:
<input min="1" max="5" class="in-range:border-green-500 ..." />
Стилизуйте поле ввода, когда его значение находится вне указанного диапазона, используя вариант out-of-range
:
<input min="1" max="5" class="out-of-range:border-red-500 ..." />
Стилизуйте поле ввода, когда отображается placeholder, используя вариант placeholder-shown
:
<input class="placeholder-shown:border-gray-500 ..." placeholder="you@example.com" />
Стилизуйте содержимое элемента <details>
с помощью варианта details-content
:
<details class="details-content:bg-gray-100 ..."> <summary>Details</summary> This is a secret.</details>
Стилизуйте поле ввода, когда оно было автоматически заполнено браузером, используя вариант autofill
:
<input class="autofill:bg-yellow-200 ..." />
Стилизуйте поле ввода, когда оно доступно только для чтения, используя вариант read-only
:
<input class="read-only:bg-gray-100 ..." />