搜索
File 2026.10.12前端开发

Tailwind CSS 4 在 Astro 里的配置

Date / 日期
Updated / 更新
2026.10.12
Reading / 阅读
6 Min
Words / 字数
1199
Category / 分类
前端开发Astro

Tailwind CSS 4 在 Astro 里的配置

· 更新于 2026年10月12日· 约 6 分钟· 1199 字

这篇和之前那篇的关系

博客最早用的是 Tailwind 3,配置写在 tailwind.config.js 里,通过 @astrojs/tailwind 集成挂上去,那套流程记在《Astro 框架中配置与使用 Tailwind CSS》。

后来重构时换成了 Tailwind 4。它最大的变化是配置搬回了 CSS:没有 tailwind.config.js,也不需要再往 content 数组里列模板路径。下面记的是现在实际在用的方式。

装配:一个 Vite 插件加一行 import

依赖只有两个:

Bash
pnpm add tailwindcss @tailwindcss/vite

tailwindcss 是核心,@tailwindcss/vite 是给 Vite 用的插件。Astro 的底层是 Vite,所以直接挂在 vite.plugins 里就行,不再需要 integrations:

astro.config.mjs
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
})

然后在样式入口的第一行把 Tailwind 整个引入:

src/styles/global.css
@import 'tailwindcss';

就这些。没有配置文件,也没有 content 数组,v4 自己扫描项目里的源文件来收集用到的类,v3 时代那个”忘了把某类文件加进 content,结果样式被 purge 掉”的问题不存在了。

dark: 跟着 data-theme 走

v4 默认的 dark: 变体看的是系统的 prefers-color-scheme。而本站的明暗是手动切换的,状态写在 <html data-theme="light|dark"> 上,跟系统偏好无关。

v3 时代这件事靠 darkMode: 'class' 加上往根元素塞一个 dark 类。v4 换成了在 CSS 里重定义变体:

CSS
/* 让 dark: 变体跟随 data-theme 属性,而不是系统偏好 */
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));

这行的意思是:命中 dark: 的工具类,选择器改写成”元素自己或它的祖先带 data-theme="dark"”。

外面包的那层 :where() 不是装饰。:where() 的特异性是 0,不加它的话这个变体会给选择器加上 [data-theme="dark"] 那部分权重,一些本该被后面工具类覆盖的规则就盖不动了。Tailwind 官方给的写法也是这样。

@theme:把已有的 CSS 变量接成工具类

站点本来就有一套颜色变量,明暗两套值分别在 :root 和暗色选择器下定义:

CSS
:root {
--c-page: #eae5e1;
--c-ink: #2a2724;
--c-accent: #9b7247;
/* … */
}

要在组件里用 Tailwind 的写法调这些颜色,就得把它们注册成主题变量。v4 用 @theme 做这件事:

CSS
@theme inline {
--color-page: var(--c-page);
--color-surface: var(--c-surface);
--color-code: var(--c-code);
--color-ink: var(--c-ink);
--color-muted: var(--c-muted);
--color-line: var(--c-line);
--color-accent: var(--c-accent);
}

注册之后就有 bg-page、text-ink、text-muted、border-line、text-accent 这些工具类了。

这里的关键是 inline。不加它,Tailwind 会把变量的值算出来写进生成的类里;加了 inline,生成的是 var(--c-ink) 这样的引用。差别在切主题的时候:站点换肤是改 <html> 上的变量值,只有引用形式才会跟着变。写死了的话,切到暗色下工具类的颜色还是原来那套。

字体栈也放在 @theme 里,不过不需要 inline,因为字体名本身就是字面量:

CSS
@theme {
--font-sans: 'MiSans', 'PingFang SC', /* … */ sans-serif;
--font-mono: 'JetBrainsMono Nerd Font', /* … */ monospace;
--font-serif: 'Times New Roman', Times, /* … */ serif;
}

定义完就有 font-sans、font-mono、font-serif 可用。其中 --font-serif 的栈是”西文衬线 + 中文无衬线”,因为中文衬线字体在这块屏幕上不好看,但英文用 Times New Roman 更合适。

一个坑:自己写的组件样式必须放进 @layer components

站点里有一批自己的排版类,比如 .rl-label。它们必须包在层里:

CSS
@layer components {
.rl-label {
font-size: 0.6875rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--c-muted);
}
}

这跟 CSS 的层叠层有关。Tailwind v4 的工具类都放在 utilities 层里,而 CSS 里没有层级的规则永远压过任何层,这跟书写顺序无关。所以不包层的话,.rl-label 里那句 color 会把元素上写的 hover:text-accent 直接吃掉,而且看代码完全看不出问题。

实际用起来是什么样

组件和页面里就直接写类名:

组件里
<div class="rounded-sm border border-line bg-surface p-4">
<span class="rl-label">DATE / 日期</span>
<p class="mt-2 text-sm text-muted">2026-10-12</p>
</div>

配合 @theme inline 注册的那批颜色,text-muted 在明暗两套主题下会各自取到对应的值,不需要写 dark: 分支。真正需要分主题调的地方才用 dark:,比如:

HTML
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">主题自适应</div>

从 v3 迁过来要改的几处

v3 的写法v4 的写法
tailwind.config.js 里的 theme.extendCSS 里的 @theme { }
content: ['./src/**/*.{html,js}']不需要,自动检测源文件
darkMode: 'class'@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *))
plugins: [require('@tailwindcss/typography')]@plugin '@tailwindcss/typography';
@tailwind base; @tailwind components; @tailwind utilities;@import 'tailwindcss';
@astrojs/tailwind 集成@tailwindcss/vite 插件

自定义工具类从 @layer utilities 里的普通规则改成了 @utility 指令,不过本站还没用到,暂时没验证过写法。

一点体会

配置搬到 CSS 之后最舒服的地方是改样式和改配置在同一个文件里。以前调一个主题色要在 tailwind.config.js 和 global.css 之间来回跳,现在是挨着的两段;而且 @theme inline 让 Tailwind 的工具类和站点原有的 CSS 变量合成了一套,不用再维护两份颜色定义。

Comment评论

添加新评论