关于 faststore-theming
faststore-theming 是用于定制 FastStore 店面的设计主题技能,面向调整颜色、字体、间距、边框及组件样式的开发者。它以设计令牌和组件数据属性为核心,并规定主题文件位置与样式选择方式。
主要功能
- 01使用全局与局部设计令牌
- 02通过 data-fs-* 属性定位组件
- 03在指定目录配置主题 SCSS
- 04为自定义组件使用 CSS Modules
- 05区分主题调整与行为覆盖
适用场景
- 01设置店面品牌颜色与字体
- 02调整特定组件的外观
- 03创建或维护 FastStore 主题
- 04判断是否需要组件覆盖
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vtex/ skills --skill faststore-theming安装后在 Claude Code 中输入/faststore-theming确认已加载。
详细介绍
FastStore 主题与设计令牌
适用场景
在以下情况下使用此技能:
- 需要更改 FastStore 店面的视觉外观,例如颜色、字体、间距、边框或组件专属样式。
- 正在处理
src/themes/中的文件,或创建custom-theme.scss。 - 需要使用本地令牌和
[data-fs-*]数据属性自定义单个组件的样式。 - 需要在 Brandless 默认主题的基础上设置品牌形象。
以下情况不要使用此技能:
- 需要替换组件、注入逻辑或修改行为时,请使用
faststore-overrides技能。 - 管理客户端状态时,请使用
faststore-state-management技能。 - 获取数据或扩展 API 时,请使用
faststore-data-fetching技能。
决策规则
- 优先使用主题设置,再考虑覆盖——这种方式更轻量,也更易维护。
- 当更改应应用于整个店面时(例如品牌颜色、字体系列),使用全局令牌(
:root作用域)。 - 当更改仅适用于单个组件时(例如按钮背景色),使用本地令牌(
[data-fs-*]作用域)。 - 使用
[data-fs-*]数据属性定位组件——切勿使用.fs-*类名或通用标签选择器。 - 将所有主题文件放在
src/themes/中,并以custom-theme.scss作为入口文件——其他位置的文件不会被发现。 - 通过
var(--fs-*)引用设计令牌,而不是硬编码十六进制颜色、像素尺寸或字体值。 - 自定义(非 FastStore)组件应使用 CSS 模块,以避免与 FastStore 的结构样式冲突。
严格约束
约束:使用设计令牌,而非内联样式
必须使用设计令牌(全局或本地)设置 FastStore 组件的样式。不得为了主题设置而在 FastStore 组件上使用内联 style={} 属性。
重要原因 内联样式会绕过设计令牌层级,无法被主题覆盖,也不会参与响应式断点,还会造成维护难题。此外,由于样式嵌入 HTML 中,它们也会破坏 CSS 缓存。设计令牌可确保一致性,并允许从单个文件更改整个店面的样式。
检测方法
如果在 FastStore 原生组件(从 @faststore/ui 或 @faststore/core 导入的组件)上看到 style={{ 或 style={ → 提醒这会绕过主题系统,并建议改用设计令牌或 CSS 模块。例外:对于不属于 FastStore UI 库的完全自定义组件,可以使用内联样式。
正确
// src/themes/custom-theme.scss
// Override the BuyButton's primary background color using design tokens
[data-fs-buy-button] {
--fs-button-primary-bkg-color: #e31c58;
--fs-button-primary-bkg-color-hover: #c4174d;
--fs-button-primary-text-color: var(--fs-color-text-inverse);
[data-fs-button-wrapper] {
border-radius: var(--fs-border-radius-pill);
}
}
错误
// WRONG: Using inline styles on a FastStore component
import { BuyButton } from '@faststore/ui'
function ProductActions() {
return (
<BuyButton
style={{ backgroundColor: '#e31c58', color: 'white', borderRadius: '999px' }}
>
Add to Cart
</BuyButton>
)
// Inline styles bypass the design token hierarchy.
// They cannot be changed store-wide from the theme file.
// They do not respond to dark mode or other theme variants.
}
约束:将主题文件放在 src/themes/ 中
必须将自定义主题 SCSS 文件放在 src/themes/ 目录中。主主题文件必须命名为 custom-theme.scss。
重要原因
FastStore 的构建系统会从 src/themes/custom-theme.scss 导入主题文件。放在其他位置的文件不会被构建流程读取,因此令牌覆盖不会生效。此时不会出现错误,而是显示默认的 Brandless 主题。
检测方法
如果在 src/themes/ 之外的 SCSS 文件中看到令牌覆盖声明(以 --fs- 开头的变量)→ 提醒这些声明可能不会生效。如果项目中不存在 src/themes/custom-theme.scss 文件 → 提醒当前没有启用自定义主题。
正确
// src/themes/custom-theme.scss
// Global token overrides — applied store-wide
:root {
--fs-color-main-0: #003232;
--fs-color-main-1: #004c4c;
--fs-color-main-2: #006666;
--fs-color-main-3: #008080;
--fs-color-main-4: #00b3b3;
--fs-color-accent-0: #e31c58;
--fs-color-accent-1: #c4174d;
--fs-color-accent-2: #a51342;
--fs-text-face-body: 'Inter', -apple-system, system-ui, BlinkMacSystemFont, sans-serif;
--fs-text-face-title: 'Poppins', var(--fs-text-face-body);
--fs-text-size-title-huge: 3.5rem;
--fs-text-size-title-page: 2.25rem;
}
// Component-specific token overrides
[data-fs-price] {
--fs-price-listing-color: #cb4242;
}
错误
// src/styles/my-theme.scss
// WRONG: This file is in src/styles/, not src/themes/
// FastStore will NOT import this file. Token overrides will be ignored.
:root {
--fs-color-main-0: #003232;
--fs-color-accent-0: #e31c58;
}
// Also WRONG: Creating a theme in the project root
// ./theme.scss — this will not be discovered by the build system
约束:使用数据属性定位组件
必须在主题 SCSS 文件中使用 FastStore 的 data-fs-* 数据属性定位组件。不得使用类名或标签选择器定位 FastStore 原生组件。
为何这很重要
FastStore 组件使用数据属性作为公开的样式 API(例如 data-fs-button、data-fs-price、data-fs-hero)。类名属于实现细节,可能会在不同版本间变更。使用数据属性可确保主题在 FastStore 更新后仍能正常使用。每个组件都会在其文档的自定义部分说明可用的数据属性。
检测
如果看到 CSS 选择器使用 .fs-* 类名或通用标签选择器(button、h1、div)来设置 FastStore 组件的样式 → 提醒其存在脆弱性。建议改用 [data-fs-*] 选择器。
正确
// src/themes/custom-theme.scss
// Target the Hero section using its data attribute
[data-fs-hero] {
--fs-hero-text-size: var(--fs-text-size-title-huge);
--fs-hero-heading-weight: var(--fs-text-weight-bold);
[data-fs-hero-heading] {
text-transform: uppercase;
letter-spacing: 0.05em;
}
[data-fs-hero-image] {
border-radius: var(--fs-border-radius);
filter: brightness(0.9);
}
}
错误
// src/themes/custom-theme.scss
// WRONG: Targeting by class names — these are internal and may change
.fs-hero {
font-size: 3.5rem;
}
.fs-hero h1 {
text-transform: uppercase;
}
// WRONG: Using generic tag selectors
section > div > h1 {
font-weight: bold;
}
// These are fragile selectors that break when FastStore restructures its HTML.
推荐模式
推荐的文件布局:
src/
└── themes/
└── custom-theme.scss ← main entry point (auto-imported by FastStore)
最精简的自定义主题:
// src/themes/custom-theme.scss
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap');
// Global Token Overrides
:root {
--fs-color-main-0: #003232;
--fs-color-main-1: #004c4c;
--fs-color-accent-0: #e31c58;
--fs-color-accent-1: #c4174d;
--fs-text-face-body: 'Inter', -apple-system, system-ui, sans-serif;
--fs-text-face-title: 'Poppins', var(--fs-text-face-body);
}
// Component-specific overrides
[data-fs-button] {
--fs-button-border-radius: var(--fs-border-radius-pill);
&[data-fs-button-variant="primary"] {
--fs-button-primary-bkg-color: var(--fs-color-accent-0);
--fs-button-primary-bkg-color-hover: var(--fs-color-accent-1);
--fs-button-primary-text-color: var(--fs-color-text-inverse);
}
}
[data-fs-price] {
--fs-price-listing-color: #cb4242;
--fs-price-listing-text-decoration: line-through;
}
[data-fs-navbar] {
--fs-navbar-bkg-color: var(--fs-color-main-0);
--fs-navbar-text-color: var(--fs-color-text-inverse);
}
对于自定义(非 FastStore)组件,请使用 CSS modules 以避免冲突:
// src/components/CustomBanner.module.scss
.customBanner {
display: flex;
align-items: center;
gap: var(--fs-spacing-3); // Still reference FastStore tokens for consistency
padding: var(--fs-spacing-4);
background-color: var(--fs-color-main-0);
color: var(--fs-color-text-inverse);
border-radius: var(--fs-border-radius);
}
常见失败模式
- 使用
!important声明——会造成特异性死局,破坏设计令牌的层叠特性。应在正确的选择器特异性下使用正确的令牌。 - 在组件样式中直接硬编码十六进制颜色、像素尺寸和字体值,而不是引用
var(--fs-*)令牌。更改无法在整个商店中生效。 - 创建与 FastStore 结构样式冲突且会使 CSS 负载翻倍的平行 CSS 系统(Tailwind、Bootstrap、自定义全局样式表)。
- 将主题文件放在
src/themes/之外——构建系统将无法发现这些文件。 - 使用
.fs-*类名或通用标签选择器,而不是[data-fs-*]数据属性来定位 FastStore 组件。
审查清单
- 主题文件是否位于
src/themes/custom-theme.scss? - 全局令牌覆盖是否放在
:root作用域中? - 组件级覆盖是否使用
[data-fs-*]数据属性选择器? - 所有值是否都通过
var(--fs-*)引用设计令牌,而非使用硬编码值? - 是否未使用
!important声明? - 是否可以不使用覆盖来实现此更改(主题设置是否足够)?
- 自定义组件样式是否使用 CSS modules 进行作用域限定,以避免冲突?
参考
- 主题概览 — 主题概念、Brandless 架构和令牌层级简介
- 全局令牌 — 所有全局设计令牌(颜色、排版、间距、边框)的完整参考
- 全局令牌:颜色 — 颜色令牌参考和调色板结构
- 全局令牌:排版 — 字体系列、字号和字重令牌
- 全局令牌:间距 — 间距比例令牌
- 设置组件样式 — 使用局部令牌自定义单个组件样式的指南
- 可用主题 — 可用作起点的预构建主题(Midnight、Soft Blue)
- 导入 FastStore UI 组件样式 — 如何在自定义区块中导入和使用组件样式
faststore-overrides— 相关技能:当仅靠主题设置不足以满足需求且需要更改行为时使用