样式 & CSS
Astro 的设计为了使设计和编写 CSS 变得轻而易举。直接在 Astro 组件中编写你自己的 CSS,或者导入你最喜欢的 CSS 库,如 Tailwind 外。也支持高级样式设计语言,如 Sass 和 Less。
在 Astro 进行设计
为 Astro 组件设计样式,就像在你的组件或页面模板上添加 <style>
标签一样容易。当你在 Astro 组件内置了 <style>
标签时,Astro 就会自动检测 CSS 并开始为你处理样式。
作用域样式
Astro <style>
标签内的 CSS 规则默认自动限定范围。作用域样式在幕后编译,只适用于写在同一组件内的 HTML。你在 Astro 组件中编写的 CSS 会自动封装在该组件中。
现有 CSS:
编译为:
作用域样式不会泄漏,也不会影响你网站的其他部分。在 Astro 中,可以使用像 h1 {}
或 p {}
这样的低特定性选择器,因为在最终输出中它们与作用域一起被编译。
作用域样式也不适用于模板内的其他 Astro 组件。如果你需要修改子组件的样式,可以考虑将该组件包裹在 <div>
(或其他元素)中,然后你就可以对其编写样式了。
作用域样式的特定性被保留,允许它们与其他 CSS 文件或 CSS 库一起工作,同时仍然保留防止样式应用于组件之外的独特边界。
全局样式
虽然我们推荐大多数组件使用范围化的样式,但有时你可能有必要使用全局的、非限定范围的 CSS。你可以通过 <style is:global>
属性选择不自动限定 CSS 范围。
你也可以使用 :global()
选择器在同一个 <style>
标签中混合全局和作用域 CSS 规则。这可以将 CSS 样式应用于子组件。
它适合用于像博客文章,或由 CMS 驱动的内容文档,这些内容在 Astro 之外的样式。但要注意会因为某个父级组件有无而导致样式不同会使得很难进行错误排查。
应尽可能多的使用作用域样式,而仅在必要时使用全局样式。
用 class:list
组合类名
如果你需要在元素上动态组合类名,你可以在 .astro
文件中使用 class:list
工具属性。
📚 参见指令参考页面,了解更多关于 class:list
的信息。
CSS 变量
添加于:astro@0.21.0
Astro <style>
可以引用页面上任何可用的 CSS 变量。你也可以在组件的 frontmatter 中直接使用 define:vars
指令来传递 CSS 变量。
📚 参见指令参考页面,了解更多关于 define:vars
的信息。
传递 class
给子组件
在 Astro 中,像 class
这样的 HTML 属性不会自动传递给子组件。
相反,你需要在子组件中接受一个 class
属性,并将其应用到根元素上。在解构时,你必须重命名它,因为 class
是 JavaScript 中的保留字。
使用默认的作用域样式策略时,你还必须传递 data-astro-cid-*
属性。你可以通过将剩余的属性 ...rest
传递给组件来实现这一点。如果你将 scopedStyleStrategy
更改为 'class'
或 'where'
,则不需要 ...rest
属性。
由于 data-astro-cid-*
属性包含了子组件在父组件的作用域中,因此父组件的样式可以传递到子组件中。为了避免这种情况,确保在子组件中使用唯一的类名。
内联样式
你可以使用 style
属性将 HTML 元素设置为内联样式。这可以是 CSS 字符串或 CSS 属性的对象:
外部样式
有两种使用外部全局样式表的方法:项目源文件中使用 ESM 导入;使用绝对链接引用 public/
目录中的文件或托管于别处的文件。
📚 阅读更多关于使用位于 public/
或 src/
的静态资源。
导入本地样式表
想要导入 npm 包,你可能需要更新 astro.config
文件。参见下面的“从 npm 包中导入样式表”部分。
你可以在 Astro 组件中使用 ESM 导入语法显式导入样式表。CSS 导入方式与 Astro 组件中的其他 ESM 导入一样,它应该基于组件进行引用,并且与其他导入一样必须位于组件脚本顶层:
任何 JavaScript 文件都支持通过 ESM import
导入 CSS,包括像 React 和 Preact 这样的 JSX 组件。这有助于为 React 组件编写细化的,具有针对性的样式
从 npm 包中导入样式表
你也可能需要从外部 npm 包中加载样式表。它常用于像导入 Open Props 这样的工具类。如果你的包建议使用文件扩展名(即 package-name/styles.css
而不是 package-name/styles
),那么它的行为应该与本地样式表一致:
如果你所用的包不建议使用文件扩展名(即 包名/样式
),那么你就需要先更新 Astro 配置
假设你从 package-name
导入名为 normalize
的 CSS 文件(省略文件扩展名)。为了确保我们能正确地预渲染你的页面,需要把package-name
添加到 vite.ssr.noExternal
数组中。
这是针对 Vite 的设置 与 Astro SSR 无关。
现在,你可以导入 package-name/normalize
了。Astro 将对其进行捆绑和优化,就像任何其他本地样式表一样。
通过 link
标签加载静态样式表
你也可以使用 <link>
元素在页面上加载样式表。它是应该位于 /public
目录下的 CSS 文件的绝对路径,或者是外部网站的链接。不支持使用相对路径的 <link>
href 值。
因为这种方法使用 public/
目录,它跳过了 Astro 提供的 CSS 处理、捆绑和压缩。如果你需要这些转换,请使用上面的导入样式表方法。
级联顺序
Astro 组件有时需要评估多个 CSS 源。例如,你的组件可能会导入 CSS 样式表,包含自己的 <style>
标签,并且被渲染在导入 CSS 的布局中。
当冲突的 CSS 规则应用于同一元素时,浏览器首先使用 特异性 和 出现顺序 来确定要显示哪个值。
如果一个规则比另一个规则更具 特异性,无论 CSS 规则出现在哪里,它的值都将具有优先权:
如果两个规则具有相同的特异性,那么将评估 出现顺序,并且最后一个规则的值将具有优先权:
Astro CSS 规则的评估顺序如下:
<link>
标签在 head 中(最低优先级)- 导入的样式
- scoped 样式(最高优先级)
作用域样式
使用 作用域样式 不会增加 CSS 的 特异性,但它们始终在 出现顺序 中最后。因此,它们将优先于具有相同特异性的其他样式。例如,如果你导入了与 scoped 样式冲突的样式表,scoped 样式的值将被应用:
如果你导入的样式更具 特异性,那么它将优先于 scoped 样式:
导入顺序
当在 Astro 组件中导入多个样式表时,将按导入的顺序评估 CSS 规则。无论何时评估 CSS,特异性总是决定要显示哪些样式。但是,当冲突的样式具有相同的特异性时,最后导入的 样式将获胜:
虽然 <style>
标签是作用域的,并且只适用于声明它们的组件,但 导入的 CSS 可以“泄漏”。导入组件会应用它导入的任何 CSS,即使该组件从未使用:
在 Astro 中,一个常见的模式是在 Layout 组件 中导入全局 CSS。请确保在其他导入之前导入 Layout 组件,以便它具有最低的优先级。
Link 标签
通过 link 标签 加载的样式表按顺序评估,优先于 Astro 文件中的任何其他样式。因此,这些样式将具有低于导入样式表和作用域样式的优先级:
CSS 集成
Astro 支持在项目中添加流行的 CSS 库、工具和框架,如 Tailwind 和其他库!
Tailwind
要在项目中使用 Tailwind,请使用包管理器的astro add
命令安装官方的 Astro Tailwind 集成:
📚 参见集成指南,了解安装、导入和配置这些集成的说明。
CSS 预处理器
Astro 支持通过 Vite 使用 CSS 预处理器,如 Sass、Stylus 和 Less。
Sass 和 SCSS
在 .astro
文件中使用 <style lang="scss">
或 <style lang="sass">
。
Stylus
在 .astro
文件中使用 <style lang="styl">
或 <style lang="stylus">
。
Less
在.astro
文件中使用 <style lang="less">
。
在框架组件中
你也可以在 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
)。
框架和库
📘 React / Preact
.jsx
文件同时支持全局 CSS 和 CSS 模块。要启用后者,请使用 .module.css
扩展名(如果使用 Sass 则是 .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 构建选项来配置样式表在多大的情况下会被链接到外部(以字节为单位)。请注意,此选项也会影响内联的脚本和图像。
如果你希望所有项目样式都保持外部样式表,可以配置 inlineStylesheets
构建选项。
你也可以将该选项设置为 'always'
,这样就可以内联所有的样式表了。
高级
绕过 Astro 内置的 CSS 捆绑时要小心!样式不会自动包含在构建的输出中,你有责任确保引用的文件被正确地包含在最终的页面输出中。
导入 ?raw
CSS
对于高级用例,CSS 可以直接从磁盘上读取,而 Astro 不进行捆绑或压缩。当你需要完全控制某些 CSS 片段,并需要绕过 Astro 的自动 CSS 处理时,这可能有用的。
对于大多数用户来说,不建议这样做:
完整的细节见 Vite 的文档。
导入 ?url
CSS
一个高级用例,你可以在你的项目 src/
目录中直接导入 CSS 文件链接。当你需要完全控制 CSS 文件在页面上的加载方式时可能有用。然而,这将阻止该 CSS 文件和你的页面上的其他 CSS 进行优化。
对于大多数用户来说,不建议这样做。相反,将 CSS 文件放在 public/
内,你可以获得一致的链接。
用 ?url
导入较小的 CSS 文件,可能会在最终构建时将 CSS 文件的 base64 编码内容作为数据链接返回值。你可以编写代码以支持经编码的数据链接(data:text/css;base64,...
),或者将 vite.build.assetsInlineLimit
配置选项设为 0
以禁用这一功能。
完整的细节见 Vite 文档。
Learn