通过在基础类前添加相应的 状态变量 ,如类似于伪类选择器的字符串,悬停 hover 、聚焦 focus 等,并用冒号 : 分隔,即可 设置相应状态下元素的样式

Tailwind 提供了多种常见的状态变量:

  • 和伪类选择器相对应的状态变量 ,如 hover focus first-child required
  • 和伪元素选择器相对应的状态变量 ,如 before after selection placeholder
  • 媒体查询相关的状态变量 ,如 sm (尺寸)、 dark (暗夜模式)、 prefers-reduced-motion (动画模式)
  • 特定元素的专属特性相关的状态变量 ,如 <details> <dialog> 元素在 open state 展开状态的样式设置可以使用状态变量 open 、字体排列顺序 RTL 或 LTR 可以使用状态属性 rtl ltr 表示
  • 💡 Tailwind 默认提供的所有状态变量,可以查看的 官方文档

    💡 这些的样式设置方式都是 inline-style 无法实现的。 而且这些状态属性可以「叠加」使用,来为元素设置在特定的几个状态同时触发时的样式

    <!-- 鼠标在按钮上悬停时,颜色变深 -->
    <!-- 在暗夜模式开启且鼠标在按钮上悬停时,颜色变浅 -->
    <button class="bg-teal-500 hover:bg-teal-600 dark:hover:bg-teal-300">Sign Up</button>
    

    根据它们的先后「叠加」次序,会生成嵌套的选择器,类似于嵌套函数。一般情况下「叠加」的状态变量的次序并无关紧要,但是有一些特殊例外?

    // These modifiers:
    'dark:group-hover:focus:opacity-100'
    // ...are applied like this:
    dark(groupHover(focus('opacity-100')))
    

    💡 所有基础类,包括自定义的基础类,都支持和状态变量配合使用

    /* 📄 main.css */
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    @layer utilities {
      .content-auto {
        content-visibility: auto;
    
    <div class="lg:content-auto">
      <!-- ... -->
    </div>
    

    伪类状态变量

    hoverfocusactivevisitedfocus-withinfocus-visible 等状态变量,一般用于设定按钮、表单等元素的相应状态的样式

    <!-- 当鼠标悬停在按钮时,背景色变浅 -->
    <!-- 当点击按钮时,背景色变深 -->
    <!-- 当按钮被聚焦时,没有默认的聚焦样式,换为自定义的样式 -->
    <button class="bg-violet-500 hover:bg-violet-400 active:bg-violet-600 focus:outline-none focus:ring focus:ring-violet-300 ...">
      Save changes
    </button>
    

    firstlast 状态变量一般用于父元素,用以设置第一或最后一个子元素的样式;oddeven 状态变量一般用于表格元素,用以设置奇数行或偶数行的样式。

    <table>
      <!-- ... -->
      <tbody>
        {#each people as person}
          <!-- Use a white background for odd rows, and gray-100 for even rows -->
          <tr class="odd:bg-white even:bg-gray-100">
            <td>{person.name}</td>
            <td>{person.title}</td>
            <td>{person.email}</td>
        {/each}
      </tbody>
    </table>
    

    💡 此外还有其他的一些不常用的表示 DOM 元素结构的状态变量:

  • only 用以设置当该元素内只有一个子元素的状态下的样式
  • {#each people as person} <li class="py-4 only:py-0 ..."> <!-- ... --> {/each}
  • first-of-type 用以设置当该元素是同类型的标签中,作为其父元素的第一个子元素的状态下的样式。另一个先对的状态变量是 last-of-type;还有作为其父元素的同类型标签唯一一个子元素的状态变量 only-of-type
  • <p class>first paragraph</p> <p>second paragraph</p> </div>
  • empty 用以设置当元素中没有内容时的样式(不仅没有子元素,也没有文本内容)
  • {#each people as person} <li class="empty:hidden ...">{person.hobby}</li> {/each}

    requiredvalidinvaliddisabledchecked 等状态变量一般用于设置表单元素在特定情况下的样式。

    💡 还包括一些不常用的状态变量:

  • default 用以设置下拉菜单的选项元素、复选框、单选按钮的默认值被加载时的表单元素的样式
  • read-only 用以设置只读表单元素的样式
  • autofill 用以设置具有自动填充属性的表单元素(它具有 autocomplete 特性)的样式
  • placeholder-shown 用以设置当占位符 placeholder 存在时表单元素的样式
  • in-rangeout-of-range 用以分别设置输入值在范围内或在范围外时表单元素的样式
    <input min="1" max="5" class="in-range:border-green-500 ..." />
    
  • indeterminate 用以设置单选按钮或复选框在不确定时的表单元素的样式
    <input type="checkbox" class="appearance-none indeterminate:bg-gray-300 ..." />
    

    group-{modifier} 状态变量用以设置子元素在父元素处于特定状态时样式,例如 group-hover 状态变量是设置当鼠标悬停在父元素(含有类名 group)时,该子元素的样式

    <!-- 父元素具有类名 group -->
    <a href="#" class="group ...">
      <!-- 子元素/目标元素具有状态变量 group-hover -->
      <p class="group-hover:text-white text-sm ...">sub element</p>
    

    💡 group-{modifier} 其中 modifier 是一种伪类状态变量,表示父元素所处的状态,例如 group-focusgroup-activegroup-odd

    peer-{modifier} 状态变量用以设置该元素在兄弟元素(含有类名 peer)处于特定状态时样式,

    <label class="block"> <!-- 兄弟元素具有类名 peer --> <input type="email" class="peer ..."/> <!-- 目标元素具有状态变量 peer-invalid --> <!-- 当以上的表单输入非法值时,该提示信息才会显示 --> <p class="invisible peer-invalid:visible ..."> Please provide a valid email address. </label> </form>

    🎬 这个视频教程就是使用该状态变量实现 floating labels 浮动标签的效果。

    伪元素状态变量

    beforeafter 状态变量用于设置伪元素 :before:after 的样式 💡 其中采用 content: '' 空字符串作为伪元素内容的默认值,如果希望设置内容可以采用 before:content-[*] 的形式,这是在元素前添加 * 字符串作为伪元素。

    <label class="block">
      <span class="after:content-['*'] after:ml-0.5 after:text-red-500 ...">
        Email
      </span>
      <input type="email" name="email" class="..." />
    </label>
    

    placeholder 状态变量为 <input type="text"/><textarea></textarea> 元素的占位符设置样式

    <label class="relative block">
      <input class="placeholder:italic placeholder:text-gray-400 ... placeholder="Search for anything..." type="text" name="search"/>
    </label>
    

    file 状态变量为 <input type="file"> 文件选择表单元素设置样式

    <form class="flex items-center space-x-6">
      <label class="block">
        <span class="sr-only">Choose profile photo</span>
        <input type="file" class="...
          file:mr-4 file:py-2 file:px-4
          file:rounded-full file:border-0
          file:text-sm file:font-semibold
          file:bg-violet-50 file:text-violet-700
          hover:file:bg-violet-100
      </label>
    </form>
    

    💡 由于 Tailwind 的样式重置 base reset 并不会应用到 <input type="file"> 元素的按钮的边框属性上,所以一般需要显式地来设置 border 相关的样式,以保持设计的统一性

    <input type="file" class="file:border file:border-solid ..." />
    

    marker 状态变量用以设置列表的各项前的标识样式

    <ul role="list" class="marker:text-sky-400 ...">
      <li>5 cups chopped mushrooms</li>
      <li>1/2 cup of olive oil</li>
      <li>3lb of celery</li>
    

    💡 该状态变量可以用在 <ul><ol> 列表元素上来统一设置列表项的样式;也可以单独应用在 <li> 元素上,分别设置该列表项的样式

    selection 状态变量用以设置选中的文本的样式

    <div class="selection:bg-fuchsia-300 selection:text-fuchsia-900">
        So I started to walk into the water.
    </div>
    

    💡 一般将该状态变量设置的基础类用于 <body> 元素以设置全局的选中文本的样式

    first-linefirst-letter 状态变量分别用于设置文本的首行或首个字母的样式

    <p class="first-line:uppercase first-line:tracking-widest
    first-letter:text-7xl first-letter:font-bold first-letter:text-gray-900
    first-letter:mr-3 first-letter:float-left
      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.
    

    媒体相关的状态变量

    Tailwind 提供了五个默认的断点 smmdlgxl2xl 这些状态变量用以设置在页面满足一定宽度时才应用的样式

    dark 用以设置当媒体特性 prefers-color-scheme 为 dark 时(即系统的主题色设置为暗色)元素的样式

    motion-reduce 用以设置当媒体特性 prefers-reduced-motion 为 reduce 时(即系统将动画效果最小化,以获得更好的性能)元素的样式,一般该状态变量用来覆盖/取消 undo那些「性能耗费高」的动效相关的样式;还有一个相对的状态变量 motion-safe 用于设置样式,一般是「性能耗费高」的动效相关的样式,它们在媒体特性 prefers-reduced-motion 不为 reduce 时才会被应用

    <!-- Using `motion-reduce` can mean lots of "undoing" styles -->
    <button class="hover:-translate-y-0.5 transition motion-reduce:hover:translate-y-0 motion-reduce:transition-none ...">
      Save changes
    </button>
    <!-- Using `motion-safe` is less code in these situations -->
    <button class="motion-safe:hover:-translate-x-0.5 motion-safe:transition ...">
      Save changes
    </button>
    

    portraitlandscape 状态变量分别用于设置当屏幕方向为纵向或横向时元素的样式

    print 状态变量用于设置元素在打印时的样式,可以用 print:hidden 基础类来实现在打印时隐藏某些元素的功能

    特性相关的状态变量

    rtlltr 状态变量分别用于设置当页面的文本显示模式为从右到左 RTL(默认情况)或从左到右 LTR 时元素的样式

    💡 如果希望 ltr 状态变量所设置的样式生效,需要指定元素的属性 dirltr(可以在页面的根元素 <html> 中进行设置)

    open 状态变量用于设置 <details><dialog> 元素为展开状态时(具有 open 特定)的样式

    <div class="max-w-lg mx-auto p-8">
      <details class="open:bg-white ... open">
        <summary class="...">
          Why do they call it Ovaltine?
        </summary>
        <div class="...">
          <p>The mug is round. The jar is round. They should call it Roundtine.</p>
        </div>
      </details>
    </div>
    

    自定义状态变量

    除了内置的状态变量,Tailwind 还支持自定义状态变量 state variants

    使用 plugins 模块在 Tailwind 的配置文件 tailwind.config.js定制 modifier

    // 📄 tailwind.config.js
    // 导入插件模块
    const plugin = require('tailwindcss/plugin');
    module.exports = {
      // ...
      plugins: [
        // 创建一个名为 third 状态变量
        // 用以匹配第三个子元素设置其样式
        plugin(function ({ addVariant }) {
          // Add a `third` variant, ie. `third:pb-0`
          addVariant('third', '&:nth-child(3)')
    

    Tailwind 提供了 dark 状态变量,用以设置暗夜模式下元素的样式。

    可以有两种方式来开启暗夜模式

    默认是基于媒体查询 prefers-color-scheme 的结果为 dark 时(即系统开启了暗夜模式时),来决定是否采用暗夜模式下的样式。

    如果希望给用户主动权,可以在页面手动切换日间或暗夜模式,可以在 Tailwind CSS 的配置文件 tailwind.config.js 中将属性 darkMode 设置为使用 class 策略,而不是默认的基于媒体查询 prefers-color-scheme(即系统设置)的 media 模式

    module.exports = {
      darkMode: 'class',
      // ...
    

    页面还需要添加相应的 JS 脚本,一般是监听按钮点击事件,控制页面根元素 <html> 的类名 dark 的增删,以实现切换 toggle 日间模式与暗夜模式

    // 以下代码兼容了随系统切换和让用户主动切换日间、暗夜模式的功能
    // On page load or when changing themes, best to add inline in `head` to avoid FOUC
    if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
      document.documentElement.classList.add('dark')
    } else {
      document.documentElement.classList.remove('dark')
    // Whenever the user explicitly chooses light mode
    localStorage.theme = 'light'
    // Whenever the user explicitly chooses dark mode
    localStorage.theme = 'dark'
    // Whenever the user explicitly chooses to respect the OS preference
    localStorage.removeItem('theme')
    

    然后会根据页面的根元素 <html> 中是否具有类名 dark 而决定是否将暗夜模式的样式应用于元素。

    <!-- Dark mode not enabled -->
      <!-- Will be white -->
      <div class="bg-white dark:bg-black">
        <!-- ... -->
      </div>
    </body>
    </html>
    
    <!-- Dark mode enabled -->
    <html class="dark">
      <!-- Will be black -->
      <div class="bg-white dark:bg-black">
        <!-- ... -->
      </div>
    </body>
    </html>
    
  •