样式方案:CSS Modules / Sass / Tailwind
本教程共 56 篇 · 第 22 篇 · 更新于 2026-08-07 · 约 9 分钟阅读
本节目标:搞懂 Astro 里怎么写样式,学完你能用作用域样式、Sass 预处理器、CSS Modules,以及接入 Tailwind 三种方案给页面排版。
样式是什么意思
“样式”就是网页长什么样:颜色、字体大小、间距、布局。在 Astro 里,你不需要额外装什么工具,就能直接写 CSS(CSS 是浏览器认识的“样式语言”)。
Astro 的设计目标是让写样式这件事尽量简单。你既可以手写普通 CSS,也能用 Tailwind 这类现成样式库,还能用 Sass 这种“进阶版 CSS”。下面我们从最基础的讲起。
组件里的样式默认是“作用域”的
在 .astro 组件里,只要写一个 <style> 标签,Astro 就会自动帮它“上锁”。所谓作用域(scoped),意思是:这段样式只对本组件内部的 HTML 生效,不会影响页面上别的组件。
看个最简单的例子:
<style>
h1 { color: red; }
</style>
你写的是 h1 { color: red; },Astro 在背后会把它编译成类似这样:
h1[data-astro-cid-hhnqfkh6] {
color: red;
}
那个 data-astro-cid-... 是一串 Astro 自动加的标记。它保证这行红色规则只作用在“当前这个组件里的 h1”,别的组件的 h1 不会跟着变红。
Note因为样式被锁在组件内部,你甚至可以放心地写
h1 {}、p {}这种“很低级”的选择器,不用担心把全站标题都改了。这是 Astro 作用域样式带来的好处。
作用域样式不会“漏”到外面,也不会应用到你模板里嵌套的其他 Astro 组件。如果你确实想给子组件加样式,常见的办法是用一个 <div> 把它包起来,再去修饰这个外层容器。
需要全局样式时用 is:global
大多数时候用作用域样式就够了。但有时你确实想写一条“全站通用”的规则,比如让所有页面的链接都变成某种颜色。这时给 <style> 加上 is:global 属性即可:
<style is:global>
/* 不加锁,原样交给浏览器,全站所有 h1 都生效 */
h1 { color: red; }
</style>
你还可以在同一个 <style> 里“混着写”:本组件用作用域,子内容用全局。靠的是 :global() 这个选择器:
<style>
/* 只作用于本组件 */
h1 { color: red; }
/* 用 :global() 包住的部分,会作用到 article 里的子 h1 */
article :global(h1) {
color: blue;
}
</style>
<h1>标题</h1>
<article><slot /></article>
这种模式很适合给博客正文、CMS 内容排版——因为这些内容本身不在 Astro 组件里,只能用全局规则去修饰。但别滥用,否则组件长什么样会依赖它的父组件,排查问题很麻烦。
Tip经验法则:能写作用域就写作用域,全局样式只在“真的需要全站统一”时才用。
用 class:list 动态拼类名
有时一个元素的 class 要按条件变化,比如“有红色边框”还是“没有”。.astro 里有个 class:list 工具能帮你在模板里拼类名:
---
const { isRed } = Astro.props;
---
<!-- isRed 为真,class 是 "box red";否则只是 "box" -->
<div class:list={['box', { red: isRed }]}><slot /></div>
<style>
.box { border: 1px solid blue; }
.red { border-color: red; }
</style>
用 CSS 变量传值给样式
CSS 变量(可以理解为“样式里的占位符”)能在不同地方复用同一个值。Astro 还允许你从组件脚本里直接把值传进 <style>,用的是 define:vars:
---
const foregroundColor = "rgb(221 243 228)";
const backgroundColor = "rgb(24 121 78)";
---
<style define:vars={{ foregroundColor, backgroundColor }}>
h1 {
background-color: var(--backgroundColor);
color: var(--foregroundColor);
}
</style>
<h1>你好</h1>
var(--backgroundColor) 就会拿到脚本里那个绿色值。
引入外部样式表
除了写在组件里,你也可以把 CSS 放进单独的文件再引入,有三种常见做法。
第一种:引入项目内的本地文件。 用普通的 import 语法,写在你组件脚本的最上方:
---
// Astro 会自动帮你打包、压缩这份 CSS
import '../styles/utils.css';
---
<html><!-- 页面内容 --></html>
第二种:引入 npm 包里的样式。 比如某些工具库自带 CSS,直接 import '包名/样式.css' 即可。若包名不带后缀,可能还要在 astro.config.mjs 里把包名加进 vite.ssr.noExternal。
第三种:用 <link> 标签加载。 适合放在 public/ 目录、或外链 CDN 的样式。注意它必须用绝对路径,不支持相对路径,而且会跳过 Astro 的压缩优化。
<head>
<link rel="stylesheet" href="/styles/global.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.24.1/themes/prism-tomorrow.css" />
</head>
多条样式的优先级(层叠顺序)
一个组件可能同时有:引入的样式表、自己的 <style>、以及外层布局引入的样式。当多条规则“打架”时,浏览器按两个原则决定谁赢:先看选择器“特指度”(越具体越优先),特指度一样时看“出现的先后顺序”(后面的赢)。
Astro 里各类样式的固定顺序是:
<link>标签(优先级最低)- import 引入的样式
- 组件内作用域样式(优先级最高)
也就是说,即使你 import 了一份样式,只要组件自己的作用域样式写了同样规则,组件内的会胜出。反过来,如果 import 的样式特指度更高(比如用了 #id 选择器),那它依然会压过作用域样式。
Sass 等 CSS 预处理器
普通 CSS 写起来有点啰嗦,没有变量、嵌套之类的便捷写法。Sass(读音像“萨斯”)就是 CSS 的“增强版”,支持嵌套、变量、混合等。Astro 内置支持 Sass、Stylus、Less 这些预处理器。
用 Sass 只需两步。先装包:
npm install sass
然后在 .astro 文件里用 lang="scss"(或 lang="sass"):
<style lang="scss">
.card {
color: #333;
&:hover { color: #000; }
}
</style>
Stylus、Less 同理,分别 npm install stylus 后写 lang="styl",或 npm install less 后写 lang="less"。另外 Astro 还支持 LightningCSS,在 astro.config.mjs 的 vite 配置里切换即可,它能更快地处理 CSS。
CSS Modules 与 UI 框架组件
“CSS Modules”是一种写法:把样式写进 xxx.module.css 这样的文件,每个类名在编译后都会变成独一无二的名字,从而避免不同文件之间的类名冲突。
需要说明:Astro 原生的作用域 <style> 已经能解决“样式不外泄”的问题,所以 .astro 文件本身不依赖 CSS Modules。CSS Modules 主要用在集成进来的 UI 框架组件里,比如 React、Preact、Vue、Svelte。
以 React 为例:
import './global.css'; // 全局样式
import Styles from './styles.module.css'; // CSS Modules(文件名必须以 .module.css 结尾)
Vue 和 Svelte 内也各自支持 CSS Modules,写法与它们官方文档一致。简单说:在框架组件里想隔离样式,就用 .module.css;在纯 .astro 组件里,直接用作用域 <style> 更顺手。
Tailwind:两种接入方式
Tailwind 是一套“实用类”样式库——你不用写 CSS 文件,而是直接在 HTML 上堆类名,比如 class="text-red-500 p-4"。Astro 同时支持 Tailwind 3 和 4,但接入方式不同,这是初学者最容易踩的坑。
Tailwind 4(新版,推荐)。 在 Astro 5.2 及以上,直接用命令行加官方 Vite 插件:
npx astro add tailwind
装好后,在一个 CSS 文件里引入 Tailwind:
@import "tailwindcss";
通常把这个文件放进 src/styles/global.css,再在布局组件里 import 一次,全站就能用 Tailwind 了。
Tailwind 3(旧版)。 需要同时装 tailwindcss@3 和 Astro 官方集成 @astrojs/tailwind,并在 astro.config.mjs 里登记:
npm install tailwindcss@3 @astrojs/tailwind
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
integrations: [tailwind()],
});
还得建一个 tailwind.config.mjs 配置文件,告诉它去扫描哪些文件。
Tip如果项目是旧的 Tailwind 3,想升级到 4:先
astro add tailwind加上新插件,再npm uninstall @astrojs/tailwind卸掉旧集成,并从配置里删掉它,最后按 Tailwind 官方升级指南改配置。二者不能共存。
为什么不只有一种样式方案
你可能会问:Astro 又是作用域样式、又是 Sass、又是 Tailwind,到底该用哪个?其实它们不冲突:
- 作用域
<style>:写组件专属的小样式,最常用。 - Sass:当你想要嵌套、变量等高级语法,又不想引整套 Tailwind。
- Tailwind:想要快速搭出整齐界面、团队统一风格时很省力。
- CSS Modules:主要在 React/Vue 等框架组件里隔离样式。
一个项目完全可以“Astro 组件用作用域样式 + 框架组件用 CSS Modules + 整体用 Tailwind”混搭。先理解每种方案的定位,再按习惯组合即可。
小结
本章我们过了 Astro 的样式全家桶:组件样式默认作用域、用 is:global 写全局、用 define:vars 传 CSS 变量、用 import 或 <link> 引入外部表;进而用 Sass 写进阶 CSS,在框架组件里用 CSS Modules,并分清 Tailwind 3(靠 @astrojs/tailwind 集成)与 Tailwind 4(靠 astro add tailwind 的 Vite 插件)两种接法。下一章我们看图片怎么优化。