Skip to content

主题与样式 ​

要让组件漂亮且正确地呈现出来,一个应用通常需要引入两样东西:主题变量,以及组件的结构样式。

ts
import { Button } from '@astryx-vue/core/Button'
import '@astryx-vue/themes/neutral.css'

当你从子路径引入 Button 时,它会自动附带按钮本身的结构骨架样式。而引入的主题样式(例如 neutral.css)则负责注入 Neutral 主题的配色变量(包含按钮所需要的 --astryx-button-* 等)。两者分工明确:如果缺少主题,组件虽然有布局结构,但会缺失色彩与视觉质感;如果缺少结构样式,变量就找不到对应的 CSS 规则来生效。

如果你不想每次手动按需引入各组件的样式,可以在全局入口处一次性加载所有样式:

ts
import '@astryx-vue/core/styles.css'
import '@astryx-vue/themes/neutral.css'

其中 styles.css 汇总了 packages/core/styles/ 下全部组件的结构样式,并自带了共享动画规则 motion.css;而 neutral.css 则汇总了 Neutral 主题的所有变量定义,并引入 Figtree 和 JetBrains Mono 字体。

样式的层级顺序(CSS Layers) ​

为了保证业务代码覆盖样式时不被组件库的特异性(Specificity)困扰,所有样式都被组织在标准的 CSS @layer 规则中,层级先后关系如下:

css
@layer astryx.reset, astryx.tokens, astryx.base, astryx.components, astryx.overrides;

如果你需要在项目中覆盖组件样式,建议将自定义样式写在 astryx.overrides 层内。需要提醒的是,普通写在未分层环境下的全局 CSS 规则优先级天然高于所有的 @layer。因此在写全局样式时,请尽量避免使用未分层的纯标签选择器(如全局写 button { ... }),以免不小心破坏掉组件的默认外观。

和 Tailwind / UnoCSS 一起用 ​

可以一起用,前提是把层的顺序定死。

关键只有一条:页面上所有层的先后,由它们第一次出现的位置决定。所以最稳的做法是在应用入口的最上面写一行,把所有层一次排好:

css
@layer theme, base, astryx.reset, astryx.tokens, astryx.base, astryx.components, astryx.overrides, components, utilities;

@import 'tailwindcss';
@import '@astryx-vue/core/styles.css';
@import '@astryx-vue/themes/neutral.css';

排在前面的层更弱,排在后面的更强。工具类那一层排在 astryx.components 后面,所以 class="p-0" 能盖掉组件自带的内边距。astryx.overrides 排在工具类前面,所以它压不过工具类。某条样式必须赢过工具类时,别靠 overrides,改顺序或者不写成分层。

顺带说一句:@layer 语句可以写在 @import 前面,这是 CSS 里少数允许的顺序。反过来的话整段会被当成无效内容丢掉。

在工具类里直接用我们的变量 ​

不用改配置,任意值写法就能用:

html
<div class="p-[var(--astryx-spacing-4)] text-[var(--astryx-color-text-primary)]">
  ...
</div>

Tailwind v4 还可以把变量登记成自己的 token,写起来更短:

css
@theme inline {
  --color-surface: var(--astryx-color-background-card);
  --color-body: var(--astryx-color-text-primary);
}

之后写 bg-surface、text-body。inline 不能省。按 Tailwind 的说明,主题值引用了另一个变量时必须加它;不加的话生成出来的工具类读的是 --color-surface 自己,而不是我们的变量,按主题作用域切换颜色时就跟不准。

UnoCSS ​

UnoCSS 默认把工具类输出成不分层的普通规则。未分层的规则赢过任何 @layer,所以工具类天然盖得住组件样式,不用调顺序。

代价是反过来的:你手写的分层 CSS 压不过 UnoCSS 的类。要盖它,选择器写具体一点,或者写成未分层。

如果你打开了 UnoCSS 的 CSS 层输出(outputToCssLayers),那就和 Tailwind 一样,把它的层排到 astryx.components 之后。

和 CSS Modules、手写 CSS 一起用 ​

这两种都能用,注意三点。

类名不会冲突。 <style module> 和 *.module.css 的类名会被改写,可以直接起名。

要盖组件内部的元素,得穿进去。 scoped 样式用 :deep(),CSS Modules 用 :global:

vue
<style module>
/* 只改组件内部那一个元素的宽度 */
.panel :global(.astryx-layout__panel) {
  width: 420px;
}
</style>

值仍然写变量。 用自己的类名可以,但颜色和间距还是写 var(--astryx-*)。抄一个 #171717 进去,深色模式和换主题就断了。

如果项目完全不用分层,就把选择器写具体一点,别用裸标签选择器(button { }),也别在全局写 * { }。

关于样式依赖 ​

这套样式不要求 UnoCSS。文档站用 UnoCSS 只为了给示例里的 i-carbon-* 类提供图标,那是图标方案,不是组件样式的依赖。见 图标。

更深入的变量命名规则、light-dark() 机制与主题支持范围,可继续阅读 CSS 变量 和 Neutral 主题。