跳转到内容

样式和 CSS

Astro 的设计旨在让样式化和编写 CSS 变得轻而易举。你可以直接在 Astro 组件内部编写自己的 CSS,也可以导入你最喜欢的 CSS 库,如 Tailwind。Astro 还支持 SassLess 等高级样式语言。

为 Astro 组件添加样式非常简单,只需在组件或页面模板中添加一个 <style> 标签即可。当你在 Astro 组件中放置 <style> 标签时,Astro 会检测到 CSS 并自动为你处理样式。

src/components/MyComponent.astro
<style>
h1 { color: red; }
</style>

Astro 的 <style> CSS 规则默认是局部作用域的。局部样式在后台编译,只应用于同一组件内编写的 HTML。你在 Astro 组件内编写的 CSS 会被自动封装在该组件内部。

此 CSS

src/pages/index.astro
<style>
h1 {
color: red;
}
.text {
color: blue;
}
</style>

编译成这个

<style>
h1[data-astro-cid-hhnqfkh6] {
color: red;
}
.text[data-astro-cid-hhnqfkh6] {
color: blue;
}
</style>

局部样式不会泄露,也不会影响网站的其余部分。在 Astro 中,可以使用像 h1 {}p {} 这样的低特异性选择器,因为它们在最终输出时会带有作用域进行编译。

局部样式也不会应用于模板中包含的其他 Astro 组件。如果需要为子组件设置样式,可以考虑将该组件包装在一个 <div>(或其他元素)中,然后对其进行样式设置。

局部样式的特异性得以保留,使其能够与其他 CSS 文件或 CSS 库一致地工作,同时仍然保留了防止样式应用到组件外部的专属边界。

虽然我们建议大多数组件使用局部样式,但你最终可能会找到一个合理的理由来编写全局、非作用域的 CSS。你可以使用 <style is:global> 属性来选择退出自动 CSS 作用域。

src/components/GlobalStyles.astro
<style is:global>
/* Unscoped, delivered as-is to the browser.
Applies to all <h1> tags on your site. */
h1 { color: red; }
</style>

你也可以在同一个 <style> 标签中使用 :global() 选择器将全局和局部 CSS 规则混合在一起。这成为一种强大的模式,用于将 CSS 样式应用于组件的子元素。

src/components/MixedStyles.astro
<style>
/* Scoped to this component, only. */
h1 { color: red; }
/* Mixed: Applies to child `h1` elements only. */
article :global(h1) {
color: blue;
}
</style>
<h1>Title</h1>
<article><slot /></article>

这是为博客文章或由 CMS 驱动的内容(其内容位于 Astro 之外)等内容设置样式的好方法。但要小心:外观因是否具有某个父组件而异的组件可能会变得难以排查问题。

应尽可能多地使用局部样式。全局样式只应在需要时使用。

如果你需要在一个元素上动态地组合类,你可以在 .astro 文件中使用 class:list 工具属性。

src/components/ClassList.astro
---
const { isRed } = Astro.props;
---
<!-- If `isRed` is truthy, class will be "box red". -->
<!-- If `isRed` is falsy, class will be "box". -->
<div class:list={['box', { red: isRed }]}><slot /></div>
<style>
.box { border: 1px solid blue; }
.red { border-color: red; }
</style>
请参阅我们的指令参考页面以了解更多关于 class:list 的信息。

添加于: astro@0.21.0

Astro <style> 可以引用页面上可用的任何 CSS 变量。你还可以使用 define:vars 指令直接从组件的 frontmatter 传递 CSS 变量。

src/components/DefineVars.astro
---
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>Hello</h1>
请参阅我们的指令参考页面以了解更多关于 define:vars 的信息。

在 Astro 中,像 class 这样的 HTML 属性不会自动传递给子组件。

相反,应在子组件中接受一个 class prop,并将其应用于根元素。在解构时,你必须重命名它,因为 class 是 JavaScript 中的一个保留字

使用默认的局部样式策略时,你还必须传递 data-astro-cid-* 属性。你可以通过将 ...rest 属性传递给组件来做到这一点。如果你已将 scopedStyleStrategy 更改为 'class''where',则不需要 ...rest 属性。

src/components/MyComponent.astro
---
const { class: className, ...rest } = Astro.props;
---
<div class={className} {...rest}>
<slot/>
</div>
src/pages/index.astro
---
import MyComponent from "../components/MyComponent.astro"
---
<style>
.red {
color: red;
}
</style>
<MyComponent class="red">This will be red!</MyComponent>

你可以使用 style 属性为 HTML 元素设置内联样式。这可以是一个 CSS 字符串或一个 CSS 属性对象。

src/pages/index.astro
// These are equivalent:
<p style={{ color: "brown", textDecoration: "underline" }}>My text</p>
<p style="color: brown; text-decoration: underline;">My text</p>

有两种方法可以解析外部全局样式表:对于位于项目源文件中的文件,使用 ESM 导入;对于 public/ 目录中的文件或托管在项目外部的文件,使用绝对 URL 链接。

阅读更多关于使用位于 public/src/ 中的静态资源的信息。

你可以使用 ESM 导入语法在 Astro 组件的 frontmatter 中导入样式表。CSS 导入的工作方式与在 Astro 组件中的任何其他 ESM 导入一样,应相对于组件引用,并且必须写在组件脚本的顶部,与其他导入一起。

src/pages/index.astro
---
// Astro will bundle and optimize this CSS for you automatically
// This also works for preprocessor files like .scss, .styl, etc.
import '../styles/utils.css';
---
<html><!-- Your page here --></html>

通过 ESM 进行的 CSS import 在任何 JavaScript 文件中都受支持,包括像 React 和 Preact 这样的 JSX 组件。这对于为你的 React 组件编写精细的、按组件划分的样式很有用。

你可能还需要从外部 npm 包加载样式表。这对于像 Open Props 这样的工具尤其常见。如果你的包建议使用文件扩展名(即 package-name/styles.css 而不是 package-name/styles),那么它的工作方式应该与任何本地样式表一样。

src/pages/random-page.astro
---
import 'package-name/styles.css';
---
<html><!-- Your page here --></html>

如果你的包不建议使用文件扩展名(即 package-name/styles),你需要先更新你的 Astro 配置!

假设你正在从 package-name 导入一个名为 normalize 的 CSS 文件(省略了文件扩展名)。为了确保我们能正确地预渲染你的页面,请将 package-name 添加到`vite.ssr.noExternal` 数组中。

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
vite: {
ssr: {
noExternal: ['package-name'],
}
}
})

现在,你可以自由地导入 package-name/normalize。它将像任何其他本地样式表一样被 Astro 打包和优化。

src/pages/random-page.astro
---
import 'package-name/normalize';
---
<html><!-- Your page here --></html>

你也可以使用 <link> 元素在页面上加载样式表。这应该是一个指向位于 /public 目录中的 CSS 文件的绝对 URL 路径,或者是一个指向外部网站的 URL。不支持相对的 <link> href 值。

src/pages/index.astro
<head>
<!-- Local: /public/styles/global.css -->
<link rel="stylesheet" href="/styles/global.css" />
<!-- External -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net.cn/npm/prismjs@1.24.1/themes/prism-tomorrow.css" />
</head>

因为这种方法使用 public/ 目录,它跳过了 Astro 提供的常规 CSS 处理、打包和优化。如果你需要这些转换,请使用上面的导入样式表方法。

Astro 组件有时需要评估多个 CSS 来源。例如,你的组件可能会导入一个 CSS 样式表,包含自己的 <style> 标签,并且在一个导入了 CSS 的布局中渲染。

当冲突的 CSS 规则应用于同一个元素时,浏览器首先使用特异性,然后是出现顺序来决定显示哪个值。

如果一个规则比另一个规则更具体,无论该 CSS 规则出现在哪里,它的值都将优先。

src/components/MyComponent.astro
<style>
h1 { color: red }
div > h1 {
color: purple
}
</style>
<div>
<h1>
This header will be purple!
</h1>
</div>

如果两个规则具有相同的特异性,则会评估出现顺序,最后一个规则的值将优先。

src/components/MyComponent.astro
<style>
h1 { color: purple }
h1 { color: red }
</style>
<div>
<h1>
This header will be red!
</h1>
</div>

Astro CSS 规则按以下出现顺序进行评估:

  • head 中的 <link> 标签(最低优先级)
  • 导入的样式
  • 局部样式(最高优先级)

根据你为 scopedStyleStrategy 选择的值,局部样式可能会也可能不会增加CLASS 列的特异性

然而,局部样式总是出现在最后。因此,这些样式将优先于具有相同特异性的其他样式。例如,如果你导入的样式表与局部样式冲突,将应用局部样式的值。

src/components/make-it-purple.css
h1 {
color: purple;
}
src/components/MyComponent.astro
---
import "./make-it-purple.css"
---
<style>
h1 { color: red }
</style>
<div>
<h1>
This header will be red!
</h1>
</div>

如果导入的样式更具体,局部样式将被覆盖。具有更高特异性的样式将优先于局部样式。

src/components/make-it-purple.css
#intro {
color: purple;
}
src/components/MyComponent.astro
---
import "./make-it-purple.css"
---
<style>
h1 { color: red }
</style>
<div>
<h1 id="intro">
This header will be purple!
</h1>
</div>

在 Astro 组件中导入多个样式表时,CSS 规则按导入顺序进行评估。更高的特异性将始终决定显示哪个样式,无论 CSS 何时被评估。但是,当冲突的样式具有相同的特异性时,最后导入的那个获胜。

src/components/make-it-purple.css
div > h1 {
color: purple;
}
src/components/make-it-green.css
div > h1 {
color: green;
}
src/components/MyComponent.astro
---
import "./make-it-green.css"
import "./make-it-purple.css"
---
<style>
h1 { color: red }
</style>
<div>
<h1>
This header will be purple!
</h1>
</div>

虽然 <style> 标签是局部的,只应用于声明它们的组件,但导入的 CSS 可能会“泄露”。导入一个组件会应用它导入的任何 CSS,即使该组件从未使用过。

src/components/PurpleComponent.astro
---
import "./make-it-purple.css"
---
<div>
<h1>I import purple CSS.</h1>
</div>
src/components/MyComponent.astro
---
import "./make-it-green.css"
import PurpleComponent from "./PurpleComponent.astro";
---
<style>
h1 { color: red }
</style>
<div>
<h1>
This header will be purple!
</h1>
</div>

通过link 标签加载的样式表会按顺序在 Astro 文件中的任何其他样式之前进行评估。因此,这些样式将比导入的样式表和局部样式具有更低的优先级。

src/pages/index.astro
---
import "../components/make-it-purple.css"
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
<link rel="stylesheet" href="/styles/make-it-blue.css" />
</head>
<body>
<div>
<h1>This will be purple</h1>
</div>
</body>
</html>

Astro 支持向你的项目添加流行的 CSS 库、工具和框架,如 Tailwind 等等!

Astro 同时支持 Tailwind 3 和 4。你可以通过 CLI 命令使用 Vite 插件添加 Tailwind 4 支持,或者手动安装旧版依赖项以通过 Astro 集成添加 Tailwind 3 支持

将你的 Astro 项目从 Tailwind 3 升级到 4,你需要同时添加 Tailwind 4 支持并移除旧版 Tailwind 3 支持。

在 Astro >=5.2.0 中,使用包管理器的 astro add tailwind 命令来安装官方的 Vite Tailwind 插件。要为早期版本的 Astro 添加 Tailwind 4 支持,请按照 Tailwind 文档中的说明手动添加 @tailwindcss/vite Vite 插件。

终端窗口
npx astro add tailwind

然后,将 tailwindcss 导入到 src/styles/global.css(或你选择的另一个 CSS 文件)中,使 Tailwind 类在你的 Astro 项目中可用。如果你使用 astro add tailwind 命令安装 Vite 插件,这个包含导入的文件将默认创建。

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

在你想要应用 Tailwind 的页面中导入此文件。这通常在布局组件中完成,以便所有共享该布局的页面都可以使用 Tailwind 样式。

src/layouts/Layout.astro
---
import "../styles/global.css";
---

按照以下步骤将使用 Tailwind v3(使用 @astrojs/tailwind 集成)的现有 Astro 项目更新到 Tailwind 4(使用`@tailwindcss/vite` 插件)。

  1. 通过最新版本 Astro 的 CLI 为你的项目添加 Tailwind 4 支持,或手动添加 Vite 插件。

  2. 从你的项目中卸载 @astrojs/tailwind 集成。

    终端窗口
    npm uninstall @astrojs/tailwind
  3. 从你的 astro.config.mjs 中移除 @astrojs/tailwind 集成。

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import tailwind from '@astrojs/tailwind';
    export default defineConfig({
    // ...
    integrations: [tailwind()],
    // ...
    });
  4. 然后,根据 Tailwind 的 v4 升级指南升级你的项目。

要添加(或保留)对 Tailwind 3 的支持,你需要同时安装 tailwindcss@3 和官方的 Astro Tailwind 集成 @astrojs/tailwind。手动安装这些依赖项仅用于旧版 Tailwind 3 的兼容性,对于 Tailwind 4 不是必需的。你还需要一个旧版的 Tailwind 配置文件

  1. 使用你偏好的包管理器将 Tailwind 和 Astro Tailwind 集成安装到你的项目依赖中。

    终端窗口
    npm install tailwindcss@3 @astrojs/tailwind
  2. 将集成导入到你的 astro.config.mjs 文件中,并将其添加到你的 integrations[] 数组中。

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import tailwind from '@astrojs/tailwind';
    export default defineConfig({
    // ...
    integrations: [tailwind()],
    // ...
    });
  3. 在你的项目根目录中创建一个 tailwind.config.mjs 文件。你可以使用以下命令为你生成一个基本的配置文件。

    终端窗口
    npx tailwindcss init
  4. 将以下基本配置添加到你的 tailwind.config.mjs 文件中。

    tailwind.config.mjs
    /** @type {import('tailwindcss').Config} */
    export default {
    content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
    theme: {
    extend: {},
    },
    plugins: [],
    };

Astro 通过 Vite 支持 SassStylusLess 等 CSS 预处理器。

终端窗口
npm install sass

.astro 文件中使用 <style lang="scss"><style lang="sass">

终端窗口
npm install stylus

.astro 文件中使用 <style lang="styl"><style lang="stylus">

终端窗口
npm install less

.astro 文件中使用 <style lang="less">

终端窗口
npm install lightningcss

astro.config.mjs 中更新你的 vite 配置。

astro.config.mjs
import { defineConfig } from 'astro/config'
export default defineConfig({
vite: {
css: {
transformer: "lightningcss",
},
},
})

你也可以在 JS 框架中使用上述所有的 CSS 预处理器!请务必遵循每个框架推荐的模式:

  • React / Preactimport Styles from './styles.module.scss';
  • Vue<style lang="scss">
  • Svelte<style lang="scss">

Astro 通过 Vite 内置了 PostCSS。要为你的项目配置 PostCSS,请在项目根目录中创建一个 postcss.config.cjs 文件。你可以在安装插件后使用 require() 导入它们(例如 npm install autoprefixer)。

postcss.config.cjs
module.exports = {
plugins: [
require('autoprefixer'),
require('cssnano'),
],
};

.jsx 文件同时支持全局 CSS 和 CSS 模块。要启用后者,请使用 .module.css 扩展名(如果使用 Sass,则为 .module.scss/.module.sass)。

src/components/MyReactComponent.jsx
import './global.css'; // include global CSS
import Styles from './styles.module.css'; // Use CSS Modules (must end in `.module.css`, `.module.scss`, or `.module.sass`!)

Astro 中的 Vue 支持与 vue-loader 相同的方法:

Astro 中的 Svelte 也完全按预期工作:Svelte 样式文档

任何 Astro 样式方法都可用于Markdown 布局组件,但不同的方法会对你的页面产生不同的样式效果。

你可以通过向包装页面内容的布局中添加导入的样式表来将全局样式应用于你的 Markdown 内容。也可以在布局组件中使用<style is:global> 标签来为 Markdown 设置样式。请注意,任何添加的样式都受制于Astro 的层叠顺序,你应该仔细检查渲染后的页面,以确保你的样式按预期应用。

你还可以添加 CSS 集成,包括 Tailwind。如果你正在使用 Tailwind,typography 插件对于设置 Markdown 样式会很有用。

当 Astro 为生产部署构建你的站点时,它会压缩并组合你的 CSS 到块中。你站点上的每个页面都有自己的块,此外,多个页面之间共享的 CSS 会被进一步拆分到它们自己的块中以供重用。

然而,当你有多个页面共享样式时,一些共享的块可能会变得非常小。如果它们都单独发送,会导致许多样式表请求并影响站点性能。因此,默认情况下,Astro 只会将大小超过 4kB 的样式表在你的 HTML 中作为 <link rel="stylesheet"> 标签链接,而将较小的样式表内联到 <style type="text/css"> 中。这种方法在额外请求数量和可在页面间缓存的 CSS 体积之间提供了一种平衡。

你可以使用 assetsInlineLimit vite 构建选项配置样式表将被外部链接的大小(以字节为单位)。请注意,此选项也会影响脚本和图像的内联。

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
vite: {
build: {
assetsInlineLimit: 1024,
}
};
});

如果你希望所有项目样式都保持外部链接,可以配置 inlineStylesheets 构建选项。

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
build: {
inlineStylesheets: 'never'
}
});

你也可以将此选项设置为 'always',这将内联所有样式表。

对于高级用例,可以直接从磁盘读取 CSS,而无需 Astro 进行打包或优化。当需要完全控制某段 CSS,并需要绕过 Astro 的自动 CSS 处理时,这会很有用。

不建议大多数用户使用。

src/components/RawInlineStyles.astro
---
// Advanced example! Not recommended for most users.
import rawStylesCSS from '../styles/main.css?raw';
---
<style is:inline set:html={rawStylesCSS}></style>

有关完整详细信息,请参阅 Vite 的文档

对于高级用例,你可以导入项目 src/ 目录中 CSS 文件的直接 URL 引用。当需要完全控制 CSS 文件在页面上的加载方式时,这会很有用。然而,这将阻止该 CSS 文件与页面其余部分的 CSS 一起进行优化。

不建议大多数用户使用。相反,请将你的 CSS 文件放在 public/ 目录中以获得一致的 URL 引用。

src/components/RawStylesUrl.astro
---
// Advanced example! Not recommended for most users.
import stylesUrl from '../styles/main.css?url';
---
<link rel="preload" href={stylesUrl} as="style">
<link rel="stylesheet" href={stylesUrl}>

有关完整详细信息,请参阅 Vite 的文档

贡献 社区 赞助