悬停、聚焦和其他状态
Tailwind 中的每个工具类都可以通过在类名的开头添加一个变体来有条件地应用,该变体描述了您想要针对的条件。
例如,要在悬停时应用 bg-sky-700 类,请使用 hover:bg-sky-700 类:
将鼠标悬停在此按钮上可查看背景颜色变化
<button class="bg-sky-500 hover:bg-sky-700 ...">Save changes</button>
这与传统 CSS 相比如何?
以传统方式编写 CSS 时,单个类名会根据当前状态执行不同的操作:
.btn-primary {
background-color: #0ea5e9;
}
.btn-primary:hover {
background-color: #0369a1;
}
在 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 ...">Save changes</button>
在本指南中,您将了解框架中可用的每个变体,如何将它们与您自己的自定义类一起使用,甚至如何创建自己的变体。
伪类
:hover、:focus 和 :active
使用 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 ...">
Save changes
</button>
Tailwind 还包括其他交互状态的变体,如 :visited 、 :focus-within 、 :focus-visible 等。
请参阅 伪类参考 以获取可用伪类变体的完整列表。
:first、:last、:odd 和 :even
当元素是第一个子元素或最后一个子元素时,使用 first 和 last 变体来设置元素的样式:
-
Kristen Ramos
kristen.ramos@example.com
-
Floyd Miles
floyd.miles@example.com
-
Courtney Henry
courtney.henry@example.com
-
Ted Fox
ted.fox@example.com
<ul role="list">
{#each people as person}
<!-- Remove top/bottom padding when first/last child -->
<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 | Senior Designer | leonard.krasner@example.com |
| Emily Selman | VP, Hardware Engineering | emily.selman@example.com |
| Anna Roberts | Chief Strategy Officer | anna.roberts@example.com |
<table>
<!-- ... -->
<tbody>
{#each people as person}
<!-- Use different background colors for odd and even rows -->
<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 和 :disabled
使用诸如 required 、 invalid 和 disabled 变体来设置不同状态下的表单元素的样式:
尝试使电子邮件地址有效以查看样式变化
<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 ..."
/>
对这类事物使用变体可以减少模板中的条件逻辑数量,让您无论输入处于什么状态都可以使用同一组类,并让浏览器为您应用正确的样式。
Tailwind 还包括其他表单状态的变体,如 :read-only 、 :indeterminate 、 :checked 等。
请参阅 伪类参考 以获取可用伪类变体的完整列表。
:has()
使用 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-* 变体来设置目标元素的样式:
TODO 存在问题,过滤器无效
Just happy to be here.
A multidisciplinary designer, working at the intersection of art and technology.
alex-reed.com
Pushing pixels. Slinging divs.
<div class="group ...">
<img src="..." />
<h4>Spencer Sharp</h4>
<svg class="hidden group-has-[a]:block ..."><!-- ... --></svg>
<p>Product Designer at <a href="...">planeteria.tech</a></p>
</div>
基于同级元素后代节点的样式设置
如果需要根据同级元素的后代来设置元素的样式,则可以用 peer 类标记同级元素,并使用 peer-has-* 变体来设置目标元素的样式:
<div>
<label class="peer ...">
<input type="checkbox" name="todo[1]" checked />
Create a to do list
</label>
<svg class="peer-has-checked:hidden ..."><!-- ... --></svg>
</div>
:not()
当条件不成立时,使用 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 ...">New project</h3>
</div>
<p class="text-gray-500 group-hover:text-white ...">Create a new project from a variety of starting templates.</p>
</a>
此模式适用于每个伪类变体,例如 group-focus 、 group-active 甚至 group-odd 。
嵌套群组的差异化处理
嵌套组时,您可以根据特定父组的状态设置某些样式,方法是使用 group/{name} 类为该父组赋予唯一的组名,并使用 group-hover/{name} 等类将该名称包含在变体中:
-
CallLeslie AbbottCo-Founder / CEO
-
CallHector AdamsVP, Marketing
-
CallBlake AlexanderAccount Coordinator
<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-\[\.is-published\]\:block {
&:is(:where(.group):is(.is-published) *) {
display: block;
}
}
您可以通过使用 & 字符来精确控制 .group 在最终生成的选择器中的相对位置,该字符标记了传入选择器中 .group 的落脚点。
<div class="group">
<!-- 当 .group 元素是其父容器中第 3 个同类型子元素时,触发子元素样式 -->
<div class="group-[:nth-of-type(3)_&]:block">
<!-- ... -->
</div>
</div>
.group-\[\:nth-of-type\(3\)_\&\]\:block {
&:is(:nth-of-type(3) :where(.group) *) {
display: block;
}
}
隐式组
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 来设置目标元素的样式:
尝试使电子邮件地址有效,以使警告消失
<form>
<label class="block">
<span class="...">Email</span>
<input type="email" class="peer ..." />
<p class="invisible peer-invalid:visible ...">Please provide a valid email address.</p>
</label>
</form>
这使得各种巧妙的技巧成为可能,例如无需任何 JS 即可实现 浮动标签 。
此模式适用于每个伪类变体,例如 peer-focus 、 peer-required 和 peer-disabled 。
需要注意的是,由于 CSS 中 后续兄弟组合器的 工作方式, peer 标记只能用于先前的兄弟:
<label>
<span class="peer-invalid:text-red-500 ...">Email</span>
<input type="email" class="peer ..." />
</label>
区分同级节点
当使用多个对等体时,您可以通过使用 peer/{name} 类为该对等体赋予唯一名称,并使用 peer-checked/{name} 等类将该名称包含在变体中,从而对特定对等体的状态进行样式化:
<fieldset>
<legend>Published status</legend>
<input id="draft" class="peer/draft" type="radio" name="status" checked />
<label for="draft" class="peer-checked/draft:text-sky-500">Draft</label>
<input id="published" class="peer/published" type="radio" name="status" />
<label for="published" class="peer-checked/published:text-sky-500">Published</label>
<div class="hidden peer-checked/draft:block">Drafts are only visible to administrators.</div>
<div class="hidden peer-checked/published:block">Your post will be publicly visible on your site.</div>
</fieldset>
您可以根据自己的喜好对等点进行命名,无需进行任何配置 - 只需在标记中直接命名您的同级,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">This field is required.</div>
<!-- ... -->
</form>
.peer-\[\.is-dirty\]\:peer-required\:block {
&:is(:where(.peer):is(.is-dirty) ~ *) {
&:is(:where(.peer):required ~ *) {
display: block;
}
}
}
为了获得更多控制,您可以使用 & 字符来标记 .peer 在相对于您传入的选择器的最终选择器中的位置:
<div>
<input type="text" class="peer" />
<div class="hidden peer-[:nth-of-type(3)_&]:block">
<!-- ... -->
</div>
</div>
.peer-\[\:nth-of-type\(3\)_\&\]\:block {
&:is(:nth-of-type(3) :where(.peer) ~ *) {
display: block;
}
}
伪元素
用于创建文档树之外的虚拟元素,例如在元素前后插入内容(::before、::after)或选中首行文本(::first-line)。它本质上是在 DOM 中生成一个不存在的新节点。
::before 和 ::after
使用 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: '' ,因此您无需指定它,除非您想要不同的值:
When you look 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>
在某些情况下,伪元素的内容不应实际存在于 DOM 中,并且不能被用户选择,此时可以使用 before 和 after。
::placeholder
使用 placeholder 变体来设置任何 input 或 textarea 占位符文本的样式:
<input
class="placeholder:text-gray-500 placeholder:italic ..."
placeholder="Search for anything..."
type="text"
name="search"
/>
::file
使用 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
使用 marker 变体来设置列表中计数器或项目符号的样式:
Ingredients
- 5 cups chopped Porcini mushrooms
- 1/2 cup of olive oil
- 3lb of celery
<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
使用 selection 变体来设置活动文本选择的样式:
尝试使用鼠标选择部分文本
So I started to walk into the water. I won't lie to you boys, I was terrified. But I pressed on, and as I made my way past the breakers a strange calm came over me. I don't know if it was divine intervention or the kinship of all living things but I tell you Jerry at that moment, I was a marine biologist.
<div class="selection:bg-fuchsia-300 selection:text-fuchsia-900">
<p>
So I started to walk into the water. I won't lie to you boys, I was terrified. But I pressed on, and as I made my
way past the breakers a strange calm came over me. I don't know if it was divine intervention or the kinship of all
living things but I tell you Jerry at that moment, I <em>was</em> a marine biologist.
</p>
</div>
我们将 selection 变体设计为可继承的,因此您可以将其添加到树中的任何位置,并且它将应用于所有后代元素。
这样可以轻松设置选择颜色以匹配整个网站的品牌:
<html>
<head>
<!-- ... -->
</head>
<body class="selection:bg-pink-300">
<!-- ... -->
</body>
</html>
::first-line 和 ::first-letter
使用 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>
::backdrop
使用 backdrop 变体来设置 原生 <dialog> 元素 的背景样式:
<dialog class="backdrop:bg-gray-50">
<form method="dialog">
<!-- ... -->
</form>
</dialog>
如果您在项目中使用原生 <dialog> 元素,您可能还想阅读有关使用 open 变体设置打开/关闭 状态样式的信息。
媒体和功能查询
响应断点
要在特定断点处设置元素的样式,请使用响应式变体,如 md 和 lg 。
例如,这将在移动设备上呈现 3 列网格,在中等宽度屏幕上呈现 4 列网格,在大宽度屏幕上呈现 6 列网格:
<div class="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6">
<!-- ... -->
</div>
要根据父元素的宽度而不是视口来设置元素的样式,请使用 @md 和 @lg 等变体:
<div class="@container">
<div class="flex flex-col @md:flex-row">
<!-- ... -->
</div>
</div>
查看 响应式设计 文档,深入了解这些功能的工作原理。
偏好配色方案
prefers-color-scheme 媒体查询用于检测用户偏好亮色主题还是暗色主题,该偏好通常由操作系统层级配置。作用:检测操作系统级别的主题偏好(亮色 light 或暗色 dark)。
基础工具类(无变体)作用于亮色模式,dark 变体类为暗色模式提供样式覆盖。
Light mode
The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.
Dark mode
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 媒体查询用于检测用户是否 请求 最小化非必要的动作。
作用:检测操作系统是否启用了 “减弱动态效果” 辅助功能(如 Windows 的 “动画效果” 设置或 macOS 的 “减少运动” 选项)。
当 用户请求减少动作 时,使用 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 辅助类需要大量 '撤销(undo)' 样式时,这一特性尤为实用:
<!-- 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 还包括 强制颜色调整 工具类,以选择加入或退出强制颜色。
反色
使用 inverted-colors 变体类,在用户启用色彩反转模式时按条件添加样式:
<div class="shadow-xl inverted-colors:shadow-none ...">
<!-- ... -->
</div>
指针精度和任意指针
pointer 媒体查询用于检测用户是否拥有主指针设备(如鼠标)及其精度。
使用 pointer-fine 变体类定位高精度指针设备(如鼠标或触控板),或使用 pointer-coarse 变体类定位低精度指针设备(如触摸屏),后者可为触控设备提供更大的点击目标:
请在开发者工具中模拟触控设备以观察样式变化
<fieldset aria-label="Choose a memory option">
<div class="flex items-center justify-between">
<div>RAM</div>
<a href="#"> See performance specs </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>This experience is designed to be viewed in landscape. Please rotate your device to view the site.</p>
</div>
</div>
脚本
使用 noscript 变体根据用户是否启用脚本(例如 JavaScript)有条件地添加样式:
<div class="hidden noscript:block">
<p>This experience requires JavaScript to function. Please enable JavaScript in your browser settings.</p>
</div>
打印
使用 print 变体有条件地添加仅在打印文档时适用的样式:
<div>
<article class="print:hidden">
<h1>My Secret Pizza Recipe</h1>
<p>This recipe is a secret, and must not be shared with anyone</p>
<!-- ... -->
</article>
<div class="hidden print:block">Are you seriously trying to print this? It's secret!</div>
</div>
@supports
使用 supports-[...] 变体根据用户浏览器是否支持某项功能来设置样式:
<div class="flex supports-[display:grid]:grid ...">
<!-- ... -->
</div>
在底层, supports-[...] 变体生成 @supports rules 并接受方括号之间使用 @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-style
使用 starting 变体类设置元素首次渲染或从 display: none 过渡为可见时的初始外观:
Update available
A new software update is available: v2.0.4.
Click the button below to install it.
<div>
<button popovertarget="my-popover">Check for updates</button>
<div popover id="my-popover" class="opacity-0 starting:open:opacity-0 ...">
<!-- ... -->
</div>
</div>
属性选择器
ARIA 状态
使用 aria-* 变体根据 ARIA 属性有条件地设置样式。
例如,要在 aria-checked 属性设置为 true 时应用 bg-sky-700 类,请使用 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 属性,请使用方括号使用任意值动态生成属性:
| Invoice # | Client | Amount |
|---|---|---|
| #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')]"
>
Invoice #
</th>
<!-- ... -->
</tr>
</thead>
<!-- ... -->
</table>
.aria-\[sort\=ascending\]\:bg-\[url\(\'\/img\/down-arrow\.svg\'\)\] {
&[aria-sort="ascending"] {
background-image: url('/img/down-arrow.svg');
}
}
.aria-\[sort\=descending\]\:bg-\[url\(\'\/img\/up-arrow\.svg\'\)\] {
&[aria-sort="descending"] {
background-image: url('/img/up-arrow.svg');
}
}
ARIA 状态变体还可以使用 group-aria-* 和 peer-aria-* 变体定位父元素和同级元素:
<table>
<thead>
<tr>
<th aria-sort="ascending" class="group">
Invoice #
<svg class="group-aria-[sort=ascending]:rotate-0 group-aria-[sort=descending]:rotate-180"><!-- ... --></svg>
</th>
<!-- ... -->
</tr>
</thead>
<!-- ... -->
</table>
.group-aria-\[sort\=ascending\]\:rotate-0 {
&:is(:where(.group)[aria-sort="ascending"] *) {
rotate: 0deg;
}
}
.group-aria-\[sort\=descending\]\:rotate-180 {
&:is(:where(.group)[aria-sort="descending"] *) {
rotate: 180deg;
}
}
数据属性
使用 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>
如果需要检查特定值,可以使用任意值:
<!-- 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-* 变体:
<div data-ui="checked active" class="data-checked:underline">
<!-- ... -->
</div>
RTL 支持
在构建多方向布局时,使用 rtl 和 ltr 变体来分别为从右到左和从左到右模式有条件地添加样式。
Left-to-right
Tom Cook
Director of Operations
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>
请记住,这些变体仅在您构建的网站需要同时支持从左到右和从右到左的布局时才有用。如果您构建的网站只需要支持单一方向,则无需这些变体 - 只需应用适合您内容的样式即可。
开/关状态
当 <details> 或 <dialog> 元素处于打开状态时,使用 open 变体有条件地添加样式:
尝试切换折叠面板,查看样式变化
Why do they call it Ovaltine?
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>
设置惰性(insert)元素样式
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>
这对于添加视觉提示很有用,可以清楚地表明内容的某些部分是不可交互的。
子选择器
直接子元素样式设置
虽然通常建议将工具类直接应用于子元素,但在需要为不可控的直接子元素设置样式时,可以使用 * 变体来实现。
Categories
<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>
为所有后代设置样式
与 * 类似,** 变体也可用于设置元素子级的样式。主要区别在于,** 会将样式应用于所有后代元素,而不仅仅是直接子级。这在结合其他变体进行精确选择时尤其有用。
-
Leslie AbbottCo-Founder / CEO
-
Hector AdamsVP, Marketing
-
Blake AlexanderAccount Coordinator
<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 中编写自定义选择器变体。
任意变体都只是用方括号括起来的表示选择器的格式字符串。例如,当元素具有 is-dragging 类时,以下任意变体会将光标更改为 grabbing :
<ul role="list">
{#each items as item}
<li class="[&.is-dragging]:cursor-grabbing">{item}</li>
{/each}
</ul>
.\[\&\.is-dragging\]\:cursor-grabbing {
&.is-dragging {
cursor: grabbing;
}
}
任意变体都可以与内置变体或彼此堆叠,就像 Tailwind 中的其他变体一样:
<ul role="list">
{#each items as item}
<li class="[&.is-dragging]:active:cursor-grabbing">{item}</li>
{/each}
</ul>
.\[\&\.is-dragging\]\:active\:cursor-grabbing {
&.is-dragging {
&:active {
cursor: grabbing;
}
}
}
若选择器中需使用空格,可用下划线替代。例如,以下任意变体将选中添加了该类的元素内所有 p 元素:
<div class="[&_p]:mt-4">
<p>Lorem ipsum...</p>
<ul>
<li>
<p>Lorem ipsum...</p>
</li>
<!-- ... -->
</ul>
</div>
.\[\&_p\]\:mt-4 {
& p {
margin-top: calc(var(--spacing) * 4);
}
}
您还可以以任意变体使用 @media 或 @supports 等规则:
<div class="flex [@supports(display:grid)]:grid">
<!-- ... -->
</div>
.\[\@supports\(display\:grid\)\]\:grid {
@supports (display:grid) {
display: grid;
}
}
在使用自定义变体的 @规则 时,无需使用 & 占位符,这与预处理器中的嵌套规则一致。
注册自定义变体
如果在项目中多次使用相同的任意变体,建议通过 @custom-variant 指令创建自定义变体:
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
现在您可以在 HTML 中使用 theme-midnight: <utility> 变体:
<html data-theme="midnight">
<button class="theme-midnight:bg-black ..."></button>
</html>
在 添加自定义变体文档 中了解有关添加自定义变体的更多信息。
附录
快速参考
Tailwind 默认包含的每个变体的快速参考表。
| 变体 | 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
当用户使用鼠标光标悬停在元素上时,使用 hover 变体设置元素的样式:
<div class="bg-black hover:bg-white ...">
<!-- ... -->
</div>
:focus
当元素获得焦点时,使用 focus 变体来设置元素的样式:
<input class="border-gray-300 focus:border-blue-400 ..." />
:focus-within
当元素或其后代之一获得焦点时,使用 focus-within 变体设置元素的样式:
<div class="focus-within:shadow-lg ...">
<input type="text" />
</div>
:focus-visible
当使用键盘聚焦元素时,使用 focus-visible 变体为其设置样式:
<button class="focus-visible:outline-2 ...">Submit</button>
:active
使用 active 变体来设置元素被按下时的样式:
<button class="bg-blue-500 active:bg-blue-600 ...">Submit</button>
:visited
当链接已经被访问时,使用 visited 变体来设置链接的样式:
<a href="https://seinfeldquotes.com" class="text-blue-600 visited:text-purple-600 ..."> Inspiration </a>
:target
使用 target 变体为 ID 与当前 URL 片段匹配的元素设置样式。
<!-- 当URL为 example.com/#about 时,以下元素会应用target变体样式 -->
<div id="about" class="target:shadow-lg ...">
<!-- ... -->
</div>
:first-child
如果元素是第一个子元素,则使用 first 变体设置其样式:
<ul>
{#each people as person}
<li class="py-4 first:pt-0 ...">
<!-- ... -->
</li>
{/each}
</ul>
:last-child
如果元素是唯一的子元素,则使用 only 变体来设置其样式:
<ul>
{#each people as person}
<li class="py-4 only:py-0 ...">
<!-- ... -->
</li>
{/each}
</ul>
:nth-child(odd)
如果元素是奇数编号的子元素,则使用 odd 变体设置其样式:
<table>
{#each people as person}
<tr class="bg-white odd:bg-gray-100 ...">
<!-- ... -->
</tr>
{/each}
</table>
:nth-child(even)
如果元素是偶数编号的子元素,则使用 even 变体设置其样式:
<table>
{#each people as person}
<tr class="bg-white even:bg-gray-100 ...">
<!-- ... -->
</tr>
{/each}
</table>
:first-of-type
如果元素是同一类型的第一个子元素,则使用 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
如果元素是同一类型的最后一个子元素,则使用 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
如果元素是同一类型的唯一子元素,则使用 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-child()
使用 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-child()
使用 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()
使用 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()
使用 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
如果元素没有内容,则使用 empty 变体设置其样式:
<ul>
{#each people as person}
<li class="empty:hidden ...">{person.hobby}</li>
{/each}
</ul>
:disabled
使用 disabled 变体来设置禁用输入时的样式:
<input class="disabled:opacity-75 ..." />
:enabled
使用 enabled 的变体在启用输入时为其设置样式,当您只想在元素未被禁用时应用另一种样式时最有用:
<input class="enabled:hover:border-gray-400 disabled:opacity-75 ..." />
:checked
使用 checked 变体来设置复选框或单选按钮被选中时的样式:
<input type="checkbox" class="appearance-none checked:bg-blue-500 ..." />
:indeterminate
使用 indeterminate 变体来设置不确定状态的复选框或单选按钮的样式:
<input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />
:default
使用 default 变体设置页面最初加载时的默认值:
<input type="checkbox" class="default:outline-2 ..." />
:required
当输入有效时,使用 valid 变体来设置输入的样式:
<input required class="border invalid:border-red-500 ..." />
:user-valid
当输入有效并且用户与其交互时,使用 user-valid 变体来设置输入的样式:
<input required class="border user-valid:border-green-500" />
:user-invalid
当输入无效且用户与其交互时,使用 user-invalid 变体来设置输入的样式:
<input required class="border user-invalid:border-red-500" />
:in-range
当输入的值在指定范围限制内时,使用 in-range 变体来设置输入的样式:
<input min="1" max="5" class="in-range:border-green-500 ..." />
:out-of-range
当输入值超出指定范围限制时,使用 out-of-range 变体对输入进行样式设置:
<input min="1" max="5" class="out-of-range:border-red-500 ..." />
:placeholder-shown
当占位符显示时,使用 placeholder-shown 变体设置输入的样式:
<input class="placeholder-shown:border-gray-500 ..." placeholder="you@example.com" />
:details-content
使用 details-content 变体来设置 <details> 元素内容的样式:
<details class="details-content:bg-gray-100 ...">
<summary>Details</summary>
This is a secret.
</details>
:autofill
当浏览器使用 autofill 变体自动填充输入时,为其设置样式:
<input class="autofill:bg-yellow-200 ..." />
:read-only
当输入为只读时,使用 read-only 变体设置输入的样式:
<input class="read-only:bg-gray-100 ..." />