Skip to content
全部文档

悬停、焦点和其他状态

Using utilities to style elements on hover, focus, and more.

Tailwind 中的每个工具类都可以通过在类名开头加上描述目标条件的变体,来有条件地应用。

例如,要在悬停时应用 bg-sky-700 类,使用 hover:bg-sky-700 类:

html
<!-- [!code classes:hover:bg-sky-700] -->
<button class="bg-sky-500 hover:bg-sky-700 ...">Save changes</button>
这和传统 CSS 相比如何?

用传统方式写 CSS 时,同一个类名会根据当前状态做不同的事:

DANGER

传统上,同一个类名在悬停时应用不同样式

css
.btn-primary {
  background-color: #0ea5e9;
}

.btn-primary:hover {
  background-color: #0369a1;
}

在 Tailwind 中,不是把悬停状态的样式加到已有类上,而是给元素再加一个在悬停时起作用的类:

TIP

在 Tailwind 中,默认状态和悬停状态使用不同的类

css
.bg-sky-500 {
  background-color: #0ea5e9;
}

.hover\:bg-sky-700:hover {
  background-color: #0369a1;
}

注意到 hover:bg-sky-700 :hover 状态定义样式吗?默认情况下它什么都不做,但一旦你悬停到带有该类的元素上,背景色就会变成 sky-700

这就是我们说工具类可以有条件地应用的意思——通过使用变体,你可以精确控制设计在不同状态下的表现,而无需离开 HTML。

Tailwind 包含你几乎会用到的所有变体,包括:

这些变体还可以叠放,以针对更具体的情况,例如在深色模式、中等断点、悬停时改变背景色:

html
<!-- [!code classes:dark:md:hover:bg-fuchsia-600] -->
<button class="dark:md:hover:bg-fuchsia-600 ...">Save changes</button>

本指南会介绍框架中的每一个变体、如何把它们用在自己的自定义类上,以及如何创建自己的变体。

伪类

:hover、:focus 和 :active

hoverfocusactive 变体为悬停、焦点和激活状态写样式:

html
<!-- [!code classes:hover:bg-violet-600,focus:outline-2,focus:outline-offset-2,focus:outline-violet-500,active:bg-violet-700] -->
<!-- prettier-ignore -->
<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

firstlast 变体,在元素是 first-child 或 last-child 时写样式:

svelte
<!-- [!code classes:first:pt-0,last:pb-0] -->
<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>

也可以用 oddeven 变体,在元素是奇数或偶数子元素时写样式:

svelte
<!-- [!code classes:odd:bg-white,even:bg-gray-50,dark:odd:bg-gray-900/50,dark:even:bg-gray-950] -->
<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-* 变体,根据子元素在列表中的位置写样式:

  • Kristen Ramos

    kristen.ramos@example.com

  • Floyd Miles

    floyd.miles@example.com

  • Courtney Henry

    courtney.henry@example.com

  • Ted Fox

    ted.fox@example.com

Name Title Email
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
html
<!-- [!code classes:nth-3:underline,nth-last-5:underline,nth-of-type-4:underline,nth-last-of-type-6:underline] -->
<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

requiredinvaliddisabled 这类变体,为表单元素的不同状态写样式:

html
<!-- [!code classes: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
  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-* 变体,根据后代的状态或内容为元素写样式:

Payment method
html
<!-- [!code classes: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]-->
<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 类,再用 group-has-* 变体为目标元素写样式:

Spencer Sharp

Product Designer at planeteria.tech

Casey Jordan

Just happy to be here.

Alex Reed

A multidisciplinary designer, working at the intersection of art and technology.

alex-reed.com

Taylor Bailey

Pushing pixels. Slinging divs.

html
<!-- [!code classes:group-has-[a]:block,group] -->
<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 类,再用 peer-has-* 变体为目标元素写样式:

Today
html
<!-- [!code classes:peer-has-checked:hidden,peer] -->
<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: 组合,只在元素未聚焦时应用悬停样式:

html
<!-- [!code classes:hover:not-focus:bg-indigo-700] -->
<button class="bg-indigo-600 hover:not-focus:bg-indigo-700">
  <!-- ... -->
</button>

也可以把 not- 变体和 forced-colorssupports 这类媒体查询变体组合,只在用户环境的某项不为真时为元素写样式:

html
<!-- [!code classes:not-supports-[display:grid]:flex] -->
<div class="not-supports-[display:grid]:flex">
  <!-- ... -->
</div>

根据父元素状态写样式

当需要根据某个元素的状态为元素写样式时,给父元素加上 group 类,再用 group-hover 这类 group-* 变体为目标元素写样式:

html
<!-- [!code classes:group-hover:stroke-white] -->
<!-- [!code classes:group-hover:text-white] -->
<!-- [!code classes:group-hover:text-white] -->
<!-- [!code classes:group] -->
<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-focusgroup-active,甚至 group-odd

区分嵌套的 group

嵌套 group 时,可以用 group/{name} 类给父元素起一个唯一的 group 名,并在变体中用 group-hover/{name} 这类类名包含该名称,从而根据特定父 group 的状态写样式:

svelte
<!-- [!code classes:group-hover/item:visible] -->
<!-- [!code classes:group-hover/edit:text-gray-700] -->
<!-- [!code classes:group-hover/edit:translate-x-0.5] -->
<!-- [!code classes:group-hover/edit:text-gray-500] -->
<!-- [!code classes:group/item] -->
<!-- [!code classes:group/edit] -->
<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>

group 可以任意命名,无需任何配置——直接在标记里命名,Tailwind 会自动生成所需 CSS。

任意 group

可以通过在方括号中提供自己的选择器作为任意值,即时创建一次性的 group-* 变体:

若要更精细地控制,可以用 & 字符标记 .group 在最终选择器中、相对于你传入的选择器应出现的位置:

隐式 group

in-* 变体的工作方式类似于 group,只不过不必给父元素加 group

html
<!-- [!code classes:in-focus:opacity-100] -->
<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-invalid 这类 peer-* 变体为目标元素写样式:

html
<!-- [!code classes:peer-invalid:visible] -->
<!-- [!code classes:peer] -->
<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-focuspeer-requiredpeer-disabled

需要注意:由于 CSS 中后续兄弟组合器的工作方式,peer 标记只能用在前面的兄弟元素上:

DANGER

无效,只有前面的兄弟元素可以被标记为 peer

html
<!-- [!code classes:peer-invalid:text-red-500] -->
<!-- [!code classes:peer] -->
<label>
  <span class="peer-invalid:text-red-500 ...">Email</span>
  <input type="email" class="peer ..." />
</label>

区分 peer

使用多个 peer 时,可以用 peer/{name} 类给该 peer 起一个唯一名称,并在变体中用 peer-checked/{name} 这类类名包含该名称,从而根据特定 peer 的状态写样式:

Published status
html
<!-- [!code classes:peer-checked/draft:block] -->
<!-- [!code classes:peer-checked/draft:text-sky-500] -->
<!-- [!code classes:peer-checked/published:text-sky-500] -->
<!-- [!code classes:peer-checked/published:block] -->
<!-- [!code classes:peer/draft] -->
<!-- [!code classes:peer/published] -->
<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>

peer 可以任意命名,无需任何配置——直接在标记里命名,Tailwind 会自动生成所需 CSS。

任意 peer

可以通过在方括号中提供自己的选择器作为任意值,即时创建一次性的 peer-* 变体:

若要更精细地控制,可以用 & 字符标记 .peer 在最终选择器中、相对于你传入的选择器应出现的位置:

伪元素

::before 和 ::after

beforeafter 变体为 ::before::after 伪元素写样式:

html
<!-- [!code classes:after:content-['*']] -->
<!-- [!code classes:after:ml-0.5] -->
<!-- [!code classes:after:text-red-500] -->
<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.
html
<!-- [!code classes:before:block] -->
<!-- [!code classes:before:absolute] -->
<!-- [!code classes:before:-inset-1] -->
<!-- [!code classes:before:-skew-y-3] -->
<!-- [!code classes:before:bg-pink-500] -->
<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 伪元素,读起来更轻松,代码实际上也更少:

html
<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>

beforeafter 留给伪元素内容确实不在 DOM 中、且不能被用户选中的场景。

::placeholder

placeholder 变体为任意 input 或 textarea 的占位文字写样式:

html
<!-- [!code classes:placeholder:italic,placeholder:text-gray-500] -->
<input
  class="placeholder:text-gray-500 placeholder:italic ..."
  placeholder="Search for anything..."
  type="text"
  name="search"
/>

::file

file 变体为文件输入中的按钮写样式:

Current profile photo
html
<!-- [!code classes: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] -->
<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
html
<!-- [!code classes:marker:text-sky-400] -->
<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.

html
<!-- [!code classes:selection:bg-fuchsia-300] -->
<!-- [!code classes:selection:text-fuchsia-900] -->
<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
<!-- [!code classes:selection:bg-pink-300] -->
<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.

html
<!-- [!code classes:first-line:uppercase] -->
<!-- [!code classes:first-line:tracking-widest] -->
<!-- [!code classes:first-letter:text-7xl] -->
<!-- [!code classes:first-letter:font-bold] -->
<!-- [!code classes:first-letter:text-gray-900] -->
<!-- [!code classes:first-letter:mr-3] -->
<!-- [!code classes:first-letter:float-left] -->
<!-- [!code classes:first-line:uppercase] -->
<!-- [!code classes:first-line:tracking-widest] -->
<!-- [!code classes:first-letter:text-7xl] -->
<!-- [!code classes:first-letter:font-bold] -->
<!-- [!code classes:first-letter:text-white] -->
<!-- [!code classes:first-letter:mr-3] -->
<!-- [!code classes:first-letter:float-left] -->
<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> 元素的背景幕写样式:

html
<!-- [!code classes:backdrop:bg-gray-50] -->
<dialog class="backdrop:bg-gray-50">
  <form method="dialog">
    <!-- ... -->
  </form>
</dialog>

如果项目中使用原生 <dialog> 元素,可能还想了解如何用 open 变体为打开/关闭状态写样式

媒体和特性查询

响应式断点

要在特定断点为元素写样式,使用 mdlg 这类响应式变体。

例如,这会在移动端渲染 3 列网格,在中等宽度屏幕渲染 4 列网格,在大宽度屏幕渲染 6 列网格:

html
<!-- [!code classes:md:grid-cols-4,lg:grid-cols-6] -->
<div class="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6">
  <!-- ... -->
</div>

要根据父元素宽度而不是视口为元素写样式,使用 @md@lg 这类变体:

html
<!-- [!code classes:@container,@md:flex-row] -->
<div class="@container">
  <div class="flex flex-col @md:flex-row">
    <!-- ... -->
  </div>
</div>

深入了解这些功能如何工作,请查看响应式设计文档。

prefers-color-scheme

prefers-color-scheme 媒体查询告诉你用户更喜欢浅色主题还是深色主题,通常在操作系统层面配置。

用不带变体的工具类针对浅色模式,用 dark 变体为深色模式提供覆盖:

Light mode

Writes upside-down

The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.

Dark mode

Writes upside-down

The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.

html
<!-- [!code classes:dark:bg-gray-900] -->
<!-- [!code classes:dark:text-white] -->
<!-- [!code classes:dark:text-gray-400] -->
<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

prefers-reduced-motion 媒体查询告诉你用户是否请求尽量减少非必要动效。

当用户请求减少动效时,用 motion-reduce 变体有条件地添加样式:

html
<!-- [!code classes:motion-reduce:hidden] -->
<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 辅助意味着必须「撤销」大量样式时,这会很有用:

html
<!-- [!code classes:motion-reduce:hover:translate-y-0] -->
<!-- [!code classes:motion-reduce:transition-none] -->
<!-- [!code classes:motion-safe:hover:-translate-x-0.5] -->
<!-- [!code classes:motion-safe:transition] -->
<!-- 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

prefers-contrast 媒体查询告诉你用户是否请求了更高或更低的对比度。

当用户请求更高对比度时,用 contrast-more 变体有条件地添加样式:

We need this to steal your identity.

html
<!-- [!code classes:contrast-more:border-gray-400,contrast-more:placeholder-gray-500,contrast-more:opacity-100] -->
<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 变体有条件地添加样式:

Choose a theme:
html
<!-- [!code classes:forced-colors:appearance-auto] -->
<!-- [!code classes:forced-colors:block] -->
<!-- [!code classes:forced-colors:hidden] -->
<!-- [!code classes:forced-colors:hidden] -->
<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 变体,在用户没有使用强制颜色模式时应用样式:

html
<!-- [!code classes:not-forced-colors:appearance-none] -->
<div class="not-forced-colors:appearance-none ...">
  <!-- ... -->
</div>

Tailwind 还包含强制颜色调整工具类,用于选择加入或退出强制颜色。

inverted-colors

当用户启用反色方案时,用 inverted-colors 变体有条件地添加样式:

html
<!-- [!code classes:inverted-colors:shadow-none] -->
<div class="shadow-xl inverted-colors:shadow-none ...">
  <!-- ... -->
</div>

pointer 和 any-pointer

pointer 媒体查询告诉你用户是否有鼠标这类主指针设备,以及该指针设备的精度。

pointer-fine 变体针对鼠标或触控板这类精确指针设备,用 pointer-coarse 变体针对触摸屏这类精度较低的指针设备,这有助于在触摸设备上提供更大的点击目标:

html
<!-- [!code classes:pointer-coarse:mt-6,pointer-coarse:grid-cols-3,pointer-coarse:gap-4,pointer-coarse:p-4] -->
<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-fineany-pointer-coarse 变体提供不同样式。

可以用 pointer-noneany-pointer-none 针对没有指针设备的情况。

orientation

当视口处于特定方向时,用 portraitlandscape 变体有条件地添加样式:

html
<!-- [!code classes:portrait:hidden,landscape:hidden] -->
<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>

scripting

根据用户是否启用了 JavaScript 这类脚本,用 noscript 变体有条件地添加样式:

html
<!-- [!code classes:noscript:block] -->
<div class="hidden noscript:block">
  <p>This experience requires JavaScript to function. Please enable JavaScript in your browser settings.</p>
</div>

print

print 变体有条件地添加仅在打印文档时生效的样式:

html
<!-- [!code classes:print:hidden] -->
<!-- [!code classes:print:block] -->
<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-[...] 变体,根据用户浏览器是否支持某项特性来写样式:

html
<!-- [!code classes:supports-[display:grid]:grid] -->
<div class="flex supports-[display:grid]:grid ...">
  <!-- ... -->
</div>

底层上,supports-[...] 变体会生成 @supports 规则,方括号里可以放任何你会和 @supports (...) 一起用的内容,例如属性/值对,甚至使用 andor 的表达式。

为了简洁,如果只需检查某个属性是否受支持(而不是特定值),只需指定属性名:

html
<!-- [!code classes:supports-backdrop-filter:bg-black/25,supports-backdrop-filter:backdrop-blur] -->
<div class="bg-black/75 supports-backdrop-filter:bg-black/25 supports-backdrop-filter:backdrop-blur ...">
  <!-- ... -->
</div>

not-supports-[...] 变体,根据用户浏览器是否不支持某项特性来写样式:

html
<!-- [!code classes:not-supports-[display:grid]:flex] -->
<div class="not-supports-[display:grid]:flex">
  <!-- ... -->
</div>

可以通过在 supports-* 命名空间中创建新变体,为项目中常用的 @supports 规则配置快捷方式:

css
@custom-variant supports-grid {
  @supports (display: grid) {
    @slot;
  }
}

然后就可以在项目中使用这些自定义 supports-* 变体:

html
<!-- [!code classes:supports-grid:grid] -->
<div class="supports-grid:grid">
  <!-- ... -->
</div>

@starting-style

starting 变体设置元素首次渲染到 DOM 时,或从 display: none 过渡到可见时的外观:

A new software update is available: v2.0.4.
Click the button below to install it.

html
<!-- [!code classes:starting:open:opacity-0] -->
<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 类:

html
<!-- [!code classes:aria-checked:bg-sky-700] -->
<div aria-checked="true" class="bg-gray-600 aria-checked:bg-sky-700">
  <!-- ... -->
</div>

默认我们为最常见的布尔 ARIA 属性包含了变体:

变体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-* 变体可用:

css
@custom-variant aria-asc (&[aria-sort="ascending"]);
@custom-variant aria-desc (&[aria-sort="descending"]);

如果需要一次性的 aria 变体、不适合放进项目,或更复杂、接受特定值的 ARIA 属性,用方括号按任意值即时生成属性:

ARIA 状态变体也可以用 group-aria-*peer-aria-* 变体针对父元素和兄弟元素:

Data 属性

data-* 变体,根据 data 属性有条件地应用样式。

要检查某个 data 属性是否存在(而不是特定值),只需指定属性名:

Invoice # Client Amount
#100 Pendant Publishing $2,000.00
#101 Kruger Industrial Smoothing $545.00
#102 J. Peterman $10,000.25
html
<!-- Will apply -->
<!-- [!code classes:data-active:border-purple-500] -->
<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>

如果需要检查特定值,可以使用任意值:

html
<!-- Will apply -->
<!-- [!code classes:data-[size=large]:p-8] -->
<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 属性配置快捷方式:

app.css
css
@import "tailwindcss";

@custom-variant data-checked (&[data-ui~="checked"]);

然后就可以在项目中使用这些自定义 data-* 变体:

html
<!-- [!code classes:data-checked:underline] -->
<div data-ui="checked active" class="data-checked:underline">
  <!-- ... -->
</div>

RTL 支持

构建多方向布局时,分别用 rtlltr 变体在从右到左和从左到右模式下有条件地添加样式:

Left-to-right

Tom Cook

Director of Operations

Right-to-left

تامر كرم

الرئيس التنفيذي

html
<!-- [!code classes:ltr:ml-3,rtl:mr-3] -->
<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.

html
<!-- [!code classes:open:border-black/10,open:bg-gray-100] -->
<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 伪类:

html
<!-- [!code classes:open:opacity-100] -->
<div>
  <button popovertarget="my-popover">Open Popover</button>
  <div popover id="my-popover" class="opacity-0 open:opacity-100 ...">
    <!-- ... -->
  </div>
</div>

为 inert 元素写样式

inert 变体让你可以为带有 inert 属性的元素写样式:

Notification preferences

Get notified when someones posts a comment on a post.

Get notified when someones mentions you.

html
<!-- [!code classes:inert:opacity-50] -->
<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

Sales
Marketing
SEO
Analytics
Design
Strategy
Security
Growth
Mobile
UX/UI
html
<!-- [!code classes:*:rounded-full] -->
<!-- [!code classes:*:border] -->
<!-- [!code classes:*:border-sky-100] -->
<!-- [!code classes:*:bg-sky-50] -->
<!-- [!code classes:*:px-2] -->
<!-- [!code classes:*:py-0.5] -->
<!-- [!code classes:dark:text-sky-300] -->
<!-- [!code classes:dark:*:border-sky-500/15] -->
<!-- [!code classes:dark:*:bg-sky-500/10] -->
<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>

需要注意:直接在子元素上用工具类覆盖样式是行不通的,因为子元素规则生成在普通规则之后,且优先级相同:

DANGER

无效,子元素无法覆盖父元素给它们的样式。

html
<!-- [!code classes:*:bg-sky-50] -->
<!-- [!code classes:bg-red-50] -->
<ul class="*:bg-sky-50 ...">
  <li class="bg-red-50 ...">Sales</li>
  <li>Marketing</li>
  <li>SEO</li>
  <!-- ... -->
</ul>

为所有后代写样式

* 一样,** 变体也可以用来为元素的子元素写样式。主要区别是 ** 会把样式应用到所有后代,而不只是直接子元素。把它和另一个变体组合以缩小选择范围时特别有用:

svelte
<!-- [!code classes:**:data-avatar:rounded-full,**:data-avatar:size-12] -->
<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

任意变体可以和内置变体叠放,也可以互相叠放,和其他 Tailwind 变体一样:

如果选择器中需要空格,可以使用下划线。例如,这个任意变体选中你添加了该类的元素内的所有 p 元素:

也可以在任意变体中使用 @media@supports 这类 at-rules:

对于 at-rule 自定义变体,不需要 & 占位符,就像用预处理器嵌套时一样。

注册自定义变体

如果发现自己在项目中多次使用同一个任意变体,可能值得用 @custom-variant 指令创建一个自定义变体:

css
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));

现在可以在 HTML 中使用 theme-midnight:<utility> 变体:

html
<!-- [!code classes:theme-midnight:bg-black] -->
<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)
print @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 变体,在用户用鼠标悬停时为元素写样式:

html
<!-- [!code classes:hover:bg-white] -->
<div class="bg-black hover:bg-white ...">
  <!-- ... -->
</div>

:focus

focus 变体,在元素获得焦点时写样式:

html
<!-- [!code classes:focus:border-blue-400] -->
<input class="border-gray-300 focus:border-blue-400 ..." />

:focus-within

focus-within 变体,在元素或其某个后代获得焦点时写样式:

html
<!-- [!code classes:focus-within:shadow-lg] -->
<div class="focus-within:shadow-lg ...">
  <input type="text" />
</div>

:focus-visible

focus-visible 变体,在元素通过键盘获得焦点时写样式:

html
<!-- [!code classes:focus-visible:outline-2] -->
<button class="focus-visible:outline-2 ...">Submit</button>

:active

active 变体,在元素被按下时写样式:

html
<!-- [!code classes:active:bg-blue-600] -->
<button class="bg-blue-500 active:bg-blue-600 ...">Submit</button>

:visited

visited 变体,在链接已被访问过时写样式:

html
<!-- [!code classes:visited:text-purple-600] -->
<a href="https://seinfeldquotes.com" class="text-blue-600 visited:text-purple-600 ..."> Inspiration </a>

:target

target 变体,在元素的 ID 匹配当前 URL 片段时写样式:

html
<!-- [!code classes:target:shadow-lg] -->
<div id="about" class="target:shadow-lg ...">
  <!-- ... -->
</div>

:first-child

first 变体,在元素是第一个子元素时写样式:

svelte
<!-- [!code classes:first:pt-0] -->
<ul>
  {#each people as person}
    <li class="py-4 first:pt-0 ...">
      <!-- ... -->
    </li>
  {/each}
</ul>

:last-child

last 变体,在元素是最后一个子元素时写样式:

svelte
<!-- [!code classes:last:pb-0] -->
<ul>
  {#each people as person}
    <li class="py-4 last:pb-0 ...">
      <!-- ... -->
    </li>
  {/each}
</ul>

:only-child

only 变体,在元素是唯一子元素时写样式:

svelte
<!-- [!code classes:only:py-0] -->
<ul>
  {#each people as person}
    <li class="py-4 only:py-0 ...">
      <!-- ... -->
    </li>
  {/each}
</ul>

:nth-child(odd)

odd 变体,在元素是奇数位子元素时写样式:

svelte
<!-- [!code classes:odd:bg-gray-100] -->
<table>
  {#each people as person}
    <tr class="bg-white odd:bg-gray-100 ...">
      <!-- ... -->
    </tr>
  {/each}
</table>

:nth-child(even)

even 变体,在元素是偶数位子元素时写样式:

svelte
<!-- [!code classes:even:bg-gray-100] -->
<table>
  {#each people as person}
    <tr class="bg-white even:bg-gray-100 ...">
      <!-- ... -->
    </tr>
  {/each}
</table>

:first-of-type

first-of-type 变体,在元素是其类型的第一个子元素时写样式:

svelte
<!-- [!code classes:first-of-type:ml-6] -->
<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 变体,在元素是其类型的最后一个子元素时写样式:

svelte
<!-- [!code classes:last-of-type:mr-6] -->
<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 变体,在元素是其类型的唯一子元素时写样式:

svelte
<!-- [!code classes:only-of-type:mx-6] -->
<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 变体,为特定位置的元素写样式:

svelte
<!-- [!code classes:nth-3:mx-6,nth-[3n+1]:mx-7] -->
<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 变体,为从末尾算起特定位置的元素写样式:

svelte
<!-- [!code classes:nth-last-3:mx-6,nth-last-[3n+1]:mx-7] -->
<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 变体,为相同类型中特定位置的元素写样式:

svelte
<!-- [!code classes:nth-of-type-3:mx-6,nth-of-type-[3n+1]:mx-7] -->
<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 变体,为相同类型中从末尾算起特定位置的元素写样式:

svelte
<!-- [!code classes:nth-last-of-type-3:mx-6,nth-last-of-type-[3n+1]:mx-7] -->
<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 变体,在元素没有内容时写样式:

svelte
<!-- [!code classes:empty:hidden] -->
<ul>
  {#each people as person}
    <li class="empty:hidden ...">{person.hobby}</li>
  {/each}
</ul>

:disabled

disabled 变体,在输入被禁用时写样式:

html
<!-- [!code classes:disabled:opacity-75] -->
<input class="disabled:opacity-75 ..." />

:enabled

enabled 变体,在输入启用时写样式;最适合只想在元素未被禁用时应用另一套样式的场景:

html
<!-- [!code classes:enabled:hover:border-gray-400] -->
<input class="enabled:hover:border-gray-400 disabled:opacity-75 ..." />

:checked

checked 变体,在复选框或单选按钮被选中时写样式:

html
<!-- [!code classes:checked:bg-blue-500] -->
<input type="checkbox" class="appearance-none checked:bg-blue-500 ..." />

:indeterminate

indeterminate 变体,在复选框或单选按钮处于不确定状态时写样式:

html
<!-- [!code classes:indeterminate:bg-gray-300] -->
<input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />

:default

default 变体,为页面初始加载时作为默认值的 option、复选框或单选按钮写样式:

html
<!-- [!code classes:default:outline-2] -->
<input type="checkbox" class="default:outline-2 ..." />

:optional

optional 变体,在输入为可选时写样式:

html
<!-- [!code classes:optional:border-red-500] -->
<input class="border optional:border-red-500 ..." />

:required

required 变体,在输入为必填时写样式:

html
<!-- [!code classes:required:border-red-500] -->
<input required class="border required:border-red-500 ..." />

:valid

valid 变体,在输入有效时写样式:

html
<!-- [!code classes:valid:border-green-500] -->
<input required class="border valid:border-green-500 ..." />

:invalid

invalid 变体,在输入无效时写样式:

html
<!-- [!code classes:invalid:border-red-500] -->
<input required class="border invalid:border-red-500 ..." />

:user-valid

user-valid 变体,在输入有效且用户已与之交互时写样式:

html
<!-- [!code classes:user-valid:border-green-500] -->
<input required class="border user-valid:border-green-500" />

:user-invalid

user-invalid 变体,在输入无效且用户已与之交互时写样式:

html
<!-- [!code classes:user-invalid:border-red-500] -->
<input required class="border user-invalid:border-red-500" />

:in-range

in-range 变体,在输入值处于指定范围限制内时写样式:

html
<!-- [!code classes:in-range:border-green-500] -->
<input min="1" max="5" class="in-range:border-green-500 ..." />

:out-of-range

out-of-range 变体,在输入值超出指定范围限制时写样式:

html
<!-- [!code classes:out-of-range:border-red-500] -->
<input min="1" max="5" class="out-of-range:border-red-500 ..." />

:placeholder-shown

placeholder-shown 变体,在显示占位符时为输入写样式:

html
<!-- [!code classes:placeholder-shown:border-gray-500] -->
<input class="placeholder-shown:border-gray-500 ..." placeholder="you@example.com" />

:details-content

details-content 变体为 <details> 元素的内容写样式:

html
<!-- [!code classes:details-content:bg-gray-100] -->
<details class="details-content:bg-gray-100 ...">
  <summary>Details</summary>
  This is a secret.
</details>

:autofill

autofill 变体,在浏览器自动填充输入时写样式:

html
<!-- [!code classes:autofill:bg-yellow-200] -->
<input class="autofill:bg-yellow-200 ..." />

:read-only

read-only 变体,在输入为只读时写样式:

html
<!-- [!code classes:read-only:bg-gray-100] -->
<input class="read-only:bg-gray-100 ..." />

文档译文以 MIT 协议授权;原文版权归 Tailwind Labs。湘ICP备2026005453号-2