import Since from '/components/Since.astro'; import PackageManagerTabs from '/components/tabs/PackageManagerTabs.astro' import ReadMore from '/components/ReadMore.astro' import { Steps } from '@astrojs/starlight/components'; import RecipeLinks from "/components/RecipeLinks.astro";

Astro 的设计为了使设计和编写 CSS 变得轻而易举。直接在 Astro 组件中编写你自己的 CSS,或者导入你最喜欢的 CSS 库,如 Tailwind 外。也支持高级样式设计语言,如 SassLess

在 Astro 进行设计

为 Astro 组件设计样式,就像在你的组件或页面模板上添加 <style> 标签一样容易。当你在 Astro 组件内置了 <style> 标签时,Astro 就会自动检测 CSS 并开始为你处理样式。

astro
<style>  h1 { color: red; }</style>

作用域样式

Astro <style> 标签内的 CSS 规则默认自动限定范围。作用域样式在幕后编译,只适用于写在同一组件内的 HTML。你在 Astro 组件中编写的 CSS 会自动封装在该组件中。

现有 CSS:

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

编译为:

astro
<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 范围。

astro
<style is:global>  /* 无作用域,直接传递给浏览器。     适用于网站上的所有 <h1> 标签。 */  h1 { color: red; }</style>

你也可以使用 :global() 选择器在同一个 <style> 标签中混合全局和作用域 CSS 规则。这可以将 CSS 样式应用于子组件。

astro
<style>  /* 仅限于此组件。 */  h1 { color: red; }  /* 混合:仅限于子组件的 <h1> 标签。 */  article :global(h1) {    color: blue;  }</style><h1>Title</h1><article><slot /></article>

它适合用于像博客文章,或由 CMS 驱动的内容文档,这些内容在 Astro 之外的样式。但要注意会因为某个父级组件有无而导致样式不同会使得很难进行错误排查。

应尽可能多的使用作用域样式,而仅在必要时使用全局样式。

class:list 组合类名

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

astro
---const { isRed } = Astro.props;---<!-- 如果 `isRed` 是真值,class 将是 "box red"。 --><!-- 如果 `isRed` 是假值,class 将是 "box"。 --><div class:list={['box', { red: isRed }]}><slot /></div><style>  .box { border: 1px solid blue; }  .red { border-color: red; }</style>

参见 指令参考 页面,了解更多关于 class:list 的信息。

CSS 变量

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

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 的信息。

传递 class 给子组件

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

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

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

astro
---const { class: className, ...rest } = Astro.props;---<div class={className} {...rest}>  <slot/></div>
astro
---import MyComponent from "../components/MyComponent.astro"---<style>  .red {    color: red;  }</style><MyComponent class="red">这将是红色!</MyComponent>

:::note[父组件的作用域类名] 由于 data-astro-cid-* 属性包含了子组件在父组件的作用域中,因此父组件的样式可以传递到子组件中。为了避免这种情况,确保在子组件中使用唯一的类名。 :::

内联样式

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

astro
// 这两种写法是等价的:<p style={{ color: "brown", textDecoration: "underline" }}>My text</p><p style="color: brown; text-decoration: underline;">My text</p>

外部样式

有两种使用外部全局样式表的方法:项目源文件中使用 ESM 导入;使用绝对链接引用 public/ 目录中的文件或托管于别处的文件。

阅读更多关于使用位于 public/src/静态资源 的内容。

导入本地样式表

:::caution[使用 npm 包?] 想要导入 npm 包,你可能需要更新 astro.config 文件。参见下面的“从 npm 包中导入样式表”部分。 :::

你可以在 Astro 组件中使用 ESM 导入语法显式导入样式表。CSS 导入方式与 Astro 组件中的其他 ESM 导入一样,它应该基于组件进行引用,并且与其他导入一样必须位于组件脚本顶层

astro
---// Astro 会自动为你捆绑和优化这些CSS。// 这也适用于预处理器文件,如 .scss、.styl 等。import '../styles/utils.css';---<html><!-- 你的页面在这 --></html>

任何 JavaScript 文件都支持通过 ESM import导入 CSS,包括像 React 和 Preact 这样的 JSX 组件。这有助于为 React 组件编写细化的,具有针对性的样式

从 npm 包中导入样式表

你也可能需要从外部 npm 包中加载样式表。它常用于像导入 Open Props 这样的工具类。如果你的包建议使用文件扩展名(即 package-name/styles.css 而不是 package-name/styles),那么它的行为应该与本地样式表一致:

astro
---// src/pages/random-page.astroimport 'package-name/styles.css';---<html><!-- 你的页面在这 --></html>

如果你所用的包不建议使用文件扩展名(即 包名/样式),那么你就需要先更新 Astro 配置!

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

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

:::note 这是针对 Vite 的设置Astro SSR 无关。 :::

现在,你可以导入 package-name/normalize 了。Astro 将对其进行捆绑和优化,就像任何其他本地样式表一样。

astro
---// src/pages/random-page.astroimport 'package-name/normalize';---<html><!-- 你的页面在这 --></html>

通过 link 标签加载静态样式表

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

astro
<head>  <!-- 本地:/public/styles/global.css -->  <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>

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

级联顺序

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

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

如果一个规则比另一个规则更具 特异性,无论 CSS 规则出现在哪里,它的值都将具有优先权:

astro
<style>  h1 { color: red }  div > h1 {    color: purple  }</style><div>  <h1>    这个 header 将会是紫色的!  </h1></div>

如果两个规则具有相同的特异性,那么将评估 出现顺序,并且最后一个规则的值将具有优先权:

astro
<style>  h1 { color: purple }  h1 { color: red }</style><div>  <h1>    这个 header 将会是红色的!  </h1></div>

Astro CSS 规则的评估顺序如下:

  • <link> 标签在 head 中(最低优先级)
  • 导入的样式
  • 作用域样式(最高优先级)

作用域样式

在作用域样式中的 类样式特异性 会基于你在 scopedStyleStrategy 中选定的值,进行增加或不进行增加。

但是,作用域样式 始终是最后才出现的。也因此,它们将优先于其他具有相同特异性的样式。例如,如果你导入了与作用域样式冲突的样式表,作用域样式的值将被应用:

css
h1 {  color: purple;}
astro
---import "./make-it-purple.css"---<style>  h1 { color: red }</style><div>  <h1>    这个 header 将会是红色的!  </h1></div>

如果导入的样式更具特异性,则作用域样式仍会被覆盖。具有更高特异性的样式将优先于作用域样式:

css
#intro {  color: purple;}
astro
---import "./make-it-purple.css"---<style>  h1 { color: red }</style><div>  <h1 id="intro">    这个 header 将会是紫色的!  </h1></div>

导入顺序

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

css
div > h1 {  color: purple;}
css
div > h1 {  color: green;}
astro
---import "./make-it-green.css"import "./make-it-purple.css"---<style>  h1 { color: red }</style><div>  <h1>    这个 header 将会是紫色的!  </h1></div>

虽然 <style> 标签是作用域的,并且只适用于声明它们的组件,但 导入的 CSS 可以“泄漏”。导入组件会应用它导入的任何 CSS,即使该组件从未使用:

astro
---import "./make-it-purple.css"---<div>  <h1>我导入紫色的 CSS。</h1></div>
astro
---import "./make-it-green.css"import PurpleComponent from "./PurpleComponent.astro";---<style>  h1 { color: red }</style><div>  <h1>    这个 header 将会是紫色的!  </h1></div>

:::tip 在 Astro 中,一个常见的模式是在 Layout 组件 中导入全局 CSS。请确保在其他导入之前导入 Layout 组件,以便它具有最低的优先级。 :::

通过 link 标签 加载的样式表按顺序评估,优先于 Astro 文件中的任何其他样式。因此,这些样式将具有低于导入样式表和作用域样式的优先级:

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>这将是紫色的</h1>		</div>	</body></html>

Tailwind

Astro 支持在项目中添加流行的 CSS 库、工具和框架,如 Tailwind 和其他库!

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

如果你要将你现有 Astro 项目的 Tailwind 3 升级到 4,你需要在添加 Tailwind 4 相关依赖的同时,删除旧版 Tailwind 3 相关依赖。

添加 Tailwind 4 支持

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

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

css
@import "tailwindcss";

将此文件导入到你希望 Tailwind 应用的页面中。这一步骤通常是在布局组件中完成的,以便 Tailwind 样式可以在共享该布局的所有页面上使用:

astro
---import "../styles/global.css";---

从 Tailwind 3 升级到 4

请遵循以下步骤,将现有的使用 Tailwind v3 的 Astro 项目(使用 @astrojs/tailwind 集成)升级到 Tailwind 4(使用 Vite 插件 @tailwindcss/vite)。

  1. @astrojs/tailwind 集成从你的项目中卸载:

  2. @astrojs/tailwind 集成从 astro.config.mjs 中删除:

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

旧版 Tailwind 3 支持

要添加(或保留)对 Tailwind 3 的支持,你将需要同时安装 tailwindcss@3 和官方的 Astro Tailwind 集成 @astrojs/tailwind。手动安装这些依赖,仅用于旧版 Tailwind 3 的兼容性,对于 Tailwind 4 并不做如此要求。你还可能会需要 旧版 Tailwind 配置

  1. 导入集成至 astro.config.mjs 文件中,并将其添加到 integrations[] 数组中:

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

  3. 将以下基础配置添加至你的 tailwind.config.mjs 文件中:

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

<RecipeLinks slugs={["zh-cn/recipes/tailwind-rendered-markdown"]}/>

CSS 预处理器

Astro 支持通过 Vite 使用 CSS 预处理器,如 SassStylusLess

Sass 和 SCSS

shell
npm install sass

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

Stylus

shell
npm install stylus

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

Less

shell
npm install less

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

LightningCSS

shell
npm install lightningcss

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

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

在框架组件中

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

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

PostCSS

Astro 内置了 PostCSS,作为 Vite 的一部分。要为你的项目配置 PostCSS,在项目根部创建 postcss.config.cjs 文件。然后你就可以在安装插件后使用 require() 导入插件(例如 npm install autoprefixer)。

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

框架和库

📘 React / Preact

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

js
import './global.css'; // 包括全局 CSSimport Styles from './styles.module.css'; // 使用 CSS 模块(必须以 `.module.css`、`.module.scss` 或 `.module.sass` 结尾!)

📗 Vue

Astro 中的 Vue 支持与 vue-loader 一样的方法。

📕 Svelte

Astro 中的 Svelte 也完全按照预期工作。Svelte Styling Docs

Markdown 样式

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

你可以通过向包装页面内容的布局中添加 导入的样式表 来将全局样式应用于 Markdown 内容。你还可以在布局组件中使用 <style is:global> 标签 来为你的 Markdown 格式设置样式。请注意,添加的任何样式都会受到 Astro 的级联顺序的影响,因此你应该仔细检查渲染后的页面,确保你的样式能够按照预期生效。

你也可以添加包括 Tailwind 在内的 CSS 集成。如果你使用 Tailwind,typography 插件 可以用于样式化 Markdown。

生产

打包控制

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

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

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

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

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

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

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

高级

:::caution 绕过 Astro 内置的 CSS 捆绑时要小心!样式不会自动包含在构建的输出中,你有责任确保引用的文件被正确地包含在最终的页面输出中。 :::

导入 ?raw CSS

对于高级用例,CSS 可以直接从磁盘上读取,而 Astro 不进行捆绑或压缩。当你需要完全控制某些 CSS 片段,并需要绕过 Astro 的自动 CSS 处理时,这可能有用的。

对于大多数用户来说,不建议这样做:

astro
---// 高级用例! 不建议大多数用户使用import rawStylesCSS from '../styles/main.css?raw';---<style is:inline set:html={rawStylesCSS}></style>

完整的细节见 Vite 的文档

导入 ?url CSS

一个高级用例,你可以在你的项目 src/ 目录中直接导入 CSS 文件链接。当你需要完全控制 CSS 文件在页面上的加载方式时可能有用。然而,这将阻止该 CSS 文件和你的页面上的其他 CSS 进行优化。

对于大多数用户来说,不建议这样做。相反,将 CSS 文件放在 public/ 内,你可以获得一致的链接。

:::caution 用 ?url 导入较小的 CSS 文件,可能会在最终构建时将 CSS 文件的 base64 编码内容作为数据链接返回值。你可以编写代码以支持经编码的数据链接(data:text/css;base64,...),或者将 vite.build.assetsInlineLimit 配置选项设为 0 以禁用这一功能。 :::

astro
---// 高级用例! 不建议大多数用户使用import stylesUrl from '../styles/main.css?url';---<link rel="preload" href={stylesUrl} as="style"><link rel="stylesheet" href={stylesUrl}>

完整的细节见 Vite 文档