Tailwind

5 阅读5分钟
  • prefers-color-scheme: 这是浏览器自带的功能,它会自动检测你的 Windows、macOS、iOS 或 Android 系统当前是处于“浅色”还是“深色”模式。

  • CSS Selector (CSS 选择器) : 在 Tailwind 中,如果你开启了手动模式,通常会在 HTML 的根元素(<html>)上添加一个 .dark 类。

    • 自动模式:系统变黑 \rightarrow 网站变黑。
    • 手动模式:HTML 标签变为 <html class="dark"> \rightarrow 网站变黑(无论系统设置如何)。

手动设置Dark模式

1. 声明自定义变体 (CSS 配置)

首先,你需要在 CSS 文件中告诉 Tailwind:不要再根据系统设置(媒体查询)来触发深色样式了,改为根据 HTML 中的 .dark 类名来触发。

app.css 中添加:

@import "tailwindcss";

/* 定义:只要当前元素或其祖先节点有 .dark 类,就启用 dark: 样式 */
@custom-variant dark (&:where(.dark, .dark *));

2. 结构准备 (HTML 结构)

在 HTML 结构中,你需要一个“开关”来手动控制根元素(通常是 <html>)的类名。

<html id="root-html" class=""> 
  <body class="bg-white dark:bg-black text-black dark:text-white">
    <button id="theme-toggle">切换模式</button>
  </body>
</html>

Tailwind 的解决方案:变量堆叠

Tailwind 并不是直接给 filter 赋值,而是定义了一套“变量占位符”。其生成的 CSS 伪代码逻辑如下:

/* Tailwind 的底层逻辑 */
:root {
  --tw-blur: ;
  --tw-brightness: ;
}

.blur-sm { --tw-blur: blur(4px); }
.brightness-50 { --tw-brightness: brightness(0.5); }

/* 核心技巧:所有的工具类最终都指向这同一个 filter 定义 */
.filter-logic-base {
  filter: var(--tw-blur) var(--tw-brightness);
}

任意值(Arbitrary Values)

核心要点总结

场景语法示例说明
特定颜色bg-[#hex]直接使用十六进制颜色。
复杂布局grid-cols-[...]处理 minmax()fr 等复杂单位。
数学计算h-[calc(...)]在类名中直接写 CSS 计算公式。
CSS 变量[--var:value]快速定义局部变量,无需写 <style> 标签。
即时编译(Just-in-Time, JIT)

Tailwind CSS 并不是你可能习惯的那种大型静态样式表——它是当你编译 CSS 时,根据你实际使用到的类名来动态生成所需的 CSS。 在找到所有潜在的类名后,Tailwind 会为每一个类生成对应的 CSS,并将其全部编译进一个只包含你真正需要的样式的样式表中。

由于 CSS 是基于类名生成的,所以 Tailwind 能够识别像 bg-[#316ff6] 这样带有任意值的类,并生成必要的 CSS,即使该值并不在你预设的主题中。

为什么它能识别 bg-[#316ff6]

因为 Tailwind 并不是在查找一个“预先定义好的颜色表”,而是在运行一个正则表达式扫描器

  1. 扫描:它看到你的代码里有 bg-[#316ff6]
  2. 解析:它识别出 bg- 前缀和方括号中的 #316ff6
  3. 生成:它在内存中实时生成一段 CSS:.bg-[#316ff6] { background-color: #316ff6; }
  4. 输出:最后这段代码被写入你的最终 CSS 文件。

⚠️ 注意事项:动态类名的坑

正如文中所说,Tailwind 是通过“扫描源码”来工作的。这意味着它不会执行你的代码

  • 错误做法className={"text-" + errorColor} (扫描器找不到完整的字符串,无法生成 CSS)。
  • 正确做法className={errorColor === 'red' ? 'text-red-500' : 'text-gray-500'} (扫描器能看到完整的类名字符串)。

这段文字介绍了 Tailwind 中非常强大的“父子级联动样式”功能:Group 状态,以及更高级的任意变体(Arbitrary Variants)

Group

Tailwind 还支持像 group-hover 这样的特性,让你可以在某个特定的父元素被悬停(hover)时,为其中的子元素设置样式:

HTML

<a href="#" class="group rounded-lg p-8">
  <span class="group-hover:underline">阅读更多…</span>
</a>

简化后的 CSS 逻辑如下:

CSS

@media (hover: hover) {
  a:hover span {
    text-decoration-line: underline;
  }
}

这种 group-* 语法也适用于其他变体,例如 group-focus(父元素获得焦点)、group-active(父元素被按下)等等。

对于极其复杂的场景(特别是当你需要为不受你控制的 HTML 编写样式时),Tailwind 支持任意变体,这让你能够直接在类名中编写任何你想要的 CSS 选择器:


核心要点总结

1. Group 状态 (The group Power)

  • 原理:在父元素标记 group 类,然后在子元素使用 group-hover: 等前缀。
  • 优势:不再局限于“悬停子元素本身才变色”,而是可以实现“悬停整个卡片时,内部的某个按钮或文字发生变化”。
  • 常见组合group-hovergroup-focusgroup-last(父元素是最后一个子元素时)。

2. 任意变体 (Arbitrary Variants)

这是 Tailwind 灵活性的顶峰。它的语法通常使用方括号 [],允许你编写复杂的 CSS 选择器。

例如:

  • [&_p]:mt-4:选中当前元素下所有的 <p> 标签并给它们设置 margin-top
  • [:nth-child(3)]:underline:选中第三个子元素并加下划线。

内联样式的使用

  • 真正的动态数据:如果你无法预知颜色(例如用户在后台自定义的品牌色),由于 Tailwind 在编译时无法生成未知的类名,必须使用 style 属性。

  • 可读性优先:当方括号内的内容(如复杂的 calcgrid)超过 50 个字符时,写在 style 里会让 HTML 结构更整洁。

  • 桥接模式(CSS 变量) :这是最高级的用法。通过 style 定义变量,再用 Tailwind 处理状态(如 hover:)。

    • 优点:内联样式很难直接处理 hover 状态,但通过变量转换后,你可以轻松写出 hover:bg-(--custom-color)