样式和 CSS
Astro 的设计为了使设计和编写 CSS 变得轻而易举。直接在 Astro 组件中编写你自己的 CSS,或者导入你最喜欢的 CSS 库,如 Tailwind 外。也支持高级样式设计语言,如 Sass 和 Less。
在 Astro 进行设计
Section titled “在 Astro 进行设计”为 Astro 组件设计样式,就像在你的组件或页面模板上添加 <style> 标签一样容易。当你在 Astro 组件内置了 <style> 标签时,Astro 就会自动检测 CSS 并开始为你处理样式。
<style> h1 { color: red; }</style>Astro <style> 标签内的 CSS 规则默认自动限定范围。作用域样式在幕后编译,只适用于写在同一组件内的 HTML。你在 Astro 组件中编写的 CSS 会自动封装在该组件中。
现有 CSS:
<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 范围。
<style is:global> /* 无作用域,直接传递给浏览器。 适用于网站上的所有 <h1> 标签。 */ h1 { color: red; }</style>你也可以使用 :global() 选择器在同一个 <style> 标签中混合全局和作用域 CSS 规则。这可以将 CSS 样式应用于子组件。
<style> /* 仅限于此组件。 */ h1 { color: red; } /* 混合:仅限于子组件的 <h1> 标签。 */ article :global(h1) { color: blue; }</style><h1>Title</h1><article><slot /></article>它适合用于像博客文章,或由 CMS 驱动的内容文档,这些内容在 Astro 之外的样式。但要注意会因为某个父级组件有无而导致样式不同会使得很难进行错误排查。
应尽可能多的使用作用域样式,而仅在必要时使用全局样式。
用 class:list 组合类名
Section titled “用 class:list 组合类名”如果你需要在元素上动态组合类名,你可以在 .astro 文件中使用 class:list 工具属性。
---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 变量
Section titled “CSS 变量”
添加于:
astro@0.21.0
Astro <style> 可以引用页面上任何可用的 CSS 变量。你也可以在组件的 frontmatter 中直接使用 define:vars 指令来传递 CSS 变量。
---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 给子组件
Section titled “传递 class 给子组件”在 Astro 中,像 class 这样的 HTML 属性不会自动传递给子组件。
相反,你需要在子组件中接受一个 class 属性,并将其应用到根元素上。在解构时,你必须重命名它,因为 class 是 JavaScript 中的保留字。
使用默认的作用域样式策略时,你还必须传递 data-astro-cid-* 属性。你可以通过将剩余的属性 ...rest 传递给组件来实现这一点。如果你将 scopedStyleStrategy 更改为 'class' 或 'where',则不需要 ...rest 属性。
---const { class: className, ...rest } = Astro.props;---<div class={className} {...rest}> <slot/></div>---import MyComponent from "../components/MyComponent.astro"---<style> .red { color: red; }</style><MyComponent class="red">这将是红色!</MyComponent>由于 data-astro-cid-* 属性包含了子组件在父组件的作用域中,因此父组件的样式可以传递到子组件中。为了避免这种情况,确保在子组件中使用唯一的类名。
你可以使用 style 属性将 HTML 元素设置为内联样式。这可以是 CSS 字符串或 CSS 属性的对象:
// 这两种写法是等价的:<p style={{ color: "brown", textDecoration: "underline" }}>My text</p><p style="color: brown; text-decoration: underline;">My text</p>有两种使用外部全局样式表的方法:项目源文件中使用 ESM 导入;使用绝对链接引用 public/ 目录中的文件或托管于别处的文件。
public/ 或 src/ 的 静态资源 的内容。
导入本地样式表
Section titled “导入本地样式表”想要导入 npm 包,你可能需要更新 astro.config 文件。参见下面的“从 npm 包中导入样式表”部分。
你可以在 Astro 组件中使用 ESM 导入语法显式导入样式表。CSS 导入方式与 Astro 组件中的其他 ESM 导入一样,它应该基于组件进行引用,并且与其他导入一样必须位于组件脚本顶层:
---// Astro 会自动为你捆绑和优化这些CSS。// 这也适用于预处理器文件,如 .scss、.styl 等。import '../styles/utils.css';---<html><!-- 你的页面在这 --></html>任何 JavaScript 文件都支持通过 ESM import导入 CSS,包括像 React 和 Preact 这样的 JSX 组件。这有助于为 React 组件编写细化的,具有针对性的样式
从 npm 包中导入样式表
Section titled “从 npm 包中导入样式表”你也可能需要从外部 npm 包中加载样式表。它常用于像导入 Open Props 这样的工具类。如果你的包建议使用文件扩展名(即 package-name/styles.css 而不是 package-name/styles),那么它的行为应该与本地样式表一致:
---import 'package-name/styles.css';---<html><!-- 你的页面在这 --></html>如果你所用的包不建议使用文件扩展名(即 包名/样式),那么你就需要先更新 Astro 配置!
假设你从 package-name 导入名为 normalize 的 CSS 文件(省略文件扩展名)。为了确保我们能正确地预渲染你的页面,需要把package-name 添加到 vite.ssr.noExternal 数组中。
import { defineConfig } from 'astro/config';
export default defineConfig({ vite: { ssr: { noExternal: ['package-name'], } }})这是针对 Vite 的设置 与 Astro SSR 无关。
现在,你可以导入 package-name/normalize 了。Astro 将对其进行捆绑和优化,就像任何其他本地样式表一样。
---import 'package-name/normalize';---<html><!-- 你的页面在这 --></html>通过 link 标签加载静态样式表
Section titled “通过 link 标签加载静态样式表”你也可以使用 <link> 元素在页面上加载样式表。它是应该位于 /public 目录下的 CSS 文件的绝对路径,或者是外部网站的链接。不支持使用相对路径的 <link> href 值。
<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 规则出现在哪里,它的值都将具有优先权:
<style> h1 { color: red } div > h1 { color: purple }</style><div> <h1> 这个 header 将会是紫色的! </h1></div>如果两个规则具有相同的特异性,那么将评估 出现顺序,并且最后一个规则的值将具有优先权:
<style> h1 { color: purple } h1 { color: red }</style><div> <h1> 这个 header 将会是红色的! </h1></div>Astro CSS 规则的评估顺序如下:
<link>标签在 head 中(最低优先级)- 导入的样式
- 作用域样式(最高优先级)
在作用域样式中的 类样式特异性 会基于你在 scopedStyleStrategy 中选定的值,进行增加或不进行增加。
但是,作用域样式 始终是最后才出现的。也因此,它们将优先于其他具有相同特异性的样式。例如,如果你导入了与作用域样式冲突的样式表,作用域样式的值将被应用:
h1 { color: purple;}---import "./make-it-purple.css"---<style> h1 { color: red }</style><div> <h1> 这个 header 将会是红色的! </h1></div>如果导入的样式更具特异性,则作用域样式仍会被覆盖。具有更高特异性的样式将优先于作用域样式:
#intro { color: purple;}---import "./make-it-purple.css"---<style> h1 { color: red }</style><div> <h1 id="intro"> 这个 header 将会是紫色的! </h1></div>当在 Astro 组件中导入多个样式表时,将按导入的顺序评估 CSS 规则。无论何时评估 CSS,特异性总是决定要显示哪些样式。但是,当冲突的样式具有相同的特异性时,最后导入的 样式将获胜:
div > h1 { color: purple;}div > h1 { color: green;}---import "./make-it-green.css"import "./make-it-purple.css"---<style> h1 { color: red }</style><div> <h1> 这个 header 将会是紫色的! </h1></div>虽然 <style> 标签是作用域的,并且只适用于声明它们的组件,但 导入的 CSS 可以“泄漏”。导入组件会应用它导入的任何 CSS,即使该组件从未使用:
---import "./make-it-purple.css"---<div> <h1>我导入紫色的 CSS。</h1></div>---import "./make-it-green.css"import PurpleComponent from "./PurpleComponent.astro";---<style> h1 { color: red }</style><div> <h1> 这个 header 将会是紫色的! </h1></div>在 Astro 中,一个常见的模式是在 Layout 组件 中导入全局 CSS。请确保在其他导入之前导入 Layout 组件,以便它具有最低的优先级。
Link 标签
Section titled “Link 标签”通过 link 标签 加载的样式表按顺序评估,优先于 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>