mcpField
S
storefront-theming

storefront-theming

github.com/finsilabs设计与 UI6089 次安装5 天前更新
代码仓库

关于 storefront-theming

面向店面开发团队的主题架构技能指南,介绍用设计令牌和 CSS 自定义属性管理品牌样式。内容涵盖深色模式、白标多租户主题及 Shopify、WooCommerce 和 BigCommerce 的配置方式。

主要功能

  1. 01设计分层令牌体系
  2. 02使用 CSS 自定义属性
  3. 03实现深色模式切换
  4. 04配置多租户品牌覆盖
  5. 05管理 Shopify、WooCommerce 和 BigCommerce 主题

适用场景

  1. 01用单一代码库支持多个品牌店面
  2. 02为店面实现深色模式
  3. 03集中调整全站品牌样式
  4. 04向团队交接可维护的设计系统

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill storefront-theming

安装后在 Claude Code 中输入/storefront-theming确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

tile.json
evals/dark-mode-implementation/
criteria.json
task.md
evals/multi-tenant-theme-injection/
criteria.json
task.md
evals/token-taxonomy-and-build-pipeline/
criteria.json
task.md

详细介绍

店面主题定制

概述

使用设计令牌和 CSS 自定义属性构建主题系统,让店面无需修改组件代码即可换用多个品牌的外观。涵盖令牌分类(颜色、排版、间距、圆角)、深色模式的运行时主题切换,以及由各租户提供自定义令牌覆盖项的白标多租户架构。

何时使用此技能

  • 构建一个基于单一代码库、支持多个品牌店面的平台时
  • 为店面实现深色模式时
  • 品牌重塑需要在数千个组件实例中更改颜色,而不必逐一查找和替换时
  • 将设计系统交接给需要维护品牌一致性的团队时

核心说明

步骤 1:确定商家的平台并选择合适的方案
平台推荐方案原因
Shopify使用主题编辑器的 Color scheme 系统,并编辑 config/settings_schema.json 和 assets/base.css 来添加自定义 CSS 变量Shopify OS2.0 主题会将所有品牌颜色、字体和边框圆角作为主题编辑器设置公开,并自动写入 CSS 变量;无需构建步骤
WooCommerce使用 WordPress Global Styles 系统(WordPress 5.9+)搭配区块主题,或为经典主题在 外观 → 自定义 → 额外 CSS 中配置 CSS 变量使用 theme.json 的区块主题原生支持完整的设计令牌系统;经典主题则需要手动添加 CSS 自定义属性
BigCommerce在 Storefront → My Themes → Customize 中配置主题设置——Cornerstone 会将颜色、字体和间距作为主题编辑器变量公开;高级自定义可通过 config.json 和 SCSS 实现Cornerstone 使用 Handlebars 模板变量编译 SCSS;可以将自定义 CSS 变量添加到全局样式表
自定义 / 无头架构使用 CSS 自定义属性构建三级令牌系统(全局 → 语义 → 组件),并通过 Style Dictionary 从 JSON 编译可全面控制令牌分类、深色模式和多租户覆盖项;请参阅下方实现
步骤 2:在平台上配置主题

Shopify

使用主题编辑器的颜色系统(无需编写代码):

  1. 前往 Online Store → Themes → Customize
  2. 点击左侧面板中的 Theme settings(油漆桶图标)
  3. 在 Colors 下配置品牌的:
    • 主色、次色和强调色
    • 背景颜色
    • 文本颜色
    • 按钮颜色和文本
  4. 在 Typography 下设置字体系列和字号
  5. 在 Buttons and inputs 下配置按钮和表单字段的边框圆角
  6. 所有更改都会写入主题中每个组件都会使用的 CSS 自定义属性——无需更改组件

添加自定义 CSS 变量(供扩展主题的开发者使用):

  1. 前往 Online Store → Themes → Edit code
  2. 打开 assets/base.css(Dawn)或等效文件
  3. 在 :root 块中添加自定义变量,并引用主题的设置变量:
:root {
  --color-button: {{ settings.color_button.red }}, {{ settings.color_button.green }}, {{ settings.color_button.blue }};
  --font-body-family: {{ settings.type_body_font.family }}, sans-serif;
}
  1. 在版块/组件 Liquid 文件中,使用 var(--color-button) 来引用由商家控制的设置

WooCommerce

使用 theme.json 的区块主题(WordPress 5.9+):

如果你正在使用区块主题(例如 Storefront Blocks 或自定义区块主题)构建新店面:

  1. 打开主题根目录中的 theme.json
  2. 将设计令牌添加到 settings.color.palette 和 settings.typography 部分:
{
  "settings": {
    "color": {
      "palette": [
        { "slug": "brand-primary", "color": "#2563eb", "name": "Brand Primary" },
        { "slug": "brand-secondary", "color": "#3b82f6", "name": "Brand Secondary" }
      ]
    },
    "custom": {
      "spacing": { "xs": "0.5rem", "sm": "1rem", "md": "1.5rem" }
    }
  }
}
  1. WordPress 会自动在 Global Styles 面板中公开这些设置,并生成类似 --wp--preset--color--brand-primary 的 CSS 自定义属性

经典主题——在额外 CSS 中使用 CSS 变量:

  1. 前往 外观 → 自定义 → 额外 CSS
  2. 定义品牌变量:
:root {
  --color-primary: #2563eb;
  --color-price-sale: #dc2626;
  --font-size-base: 1rem;
  --border-radius-button: 0.375rem;
}
  1. 在子主题的 CSS 中使用这些变量,而不要使用硬编码值

BigCommerce

Cornerstone 主题变量(基于 SCSS):

  1. 前往 Storefront → My Themes → Edit Theme Files(需要复制一份主题)
  2. 打开 assets/scss/settings/global/ — Cornerstone 按类别(颜色、排版、间距)组织变量
  3. 修改 _color.scss 以更新品牌配色
  4. 打开主题根目录中的 config.json — 该文件将主题编辑器控件映射到 SCSS 变量:
{
  "settings": {
    "color-primary": "#2563eb",
    "font-size-root": "16px",
    "button-radius": "4px"
  }
}
  1. 在 Storefront → My Themes → Customize 中,主题编辑器会显示这些设置,供商家配置

自定义 / 无头架构

三级 CSS 自定义属性系统:

/* 1. Global tokens — the complete palette (never used directly in components) */
:root {
  --blue-600: #2563eb;
  --blue-500: #3b82f6;
  --red-500: #ef4444;
  --green-600: #16a34a;
  --gray-50: #f8fafc;
  --gray-900: #0f172a;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --radius-md: 0.375rem;
}

/* 2. Semantic tokens — meaningful aliases (components consume these) */
:root {
  --color-brand-primary: var(--blue-600);
  --color-brand-secondary: var(--blue-500);
  --color-surface: var(--gray-50);
  --color-on-surface: var(--gray-900);
  --color-price: var(--gray-900);
  --color-price-sale: var(--red-500);
  --color-success: var(--green-600);
}

/* 3. Dark mode overrides */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-surface: var(--gray-900);
    --color-on-surface: var(--gray-50);
  }
}
[data-theme="dark"] {
  --color-surface: var(--gray-900);
  --color-on-surface: var(--gray-50);
}

/* Components only use semantic tokens */
.btn-primary {
  background: var(--color-brand-primary);
  border-radius: var(--radius-md);
  min-height: 44px;
}
.price--sale { color: var(--color-price-sale); }

深色模式切换(在 localStorage 中保存偏好设置):

export function ThemeToggle() {
  const [theme, setTheme] = useState(() => localStorage.getItem('theme') ?? 'system');

  function applyTheme(newTheme) {
    setTheme(newTheme);
    localStorage.setItem('theme', newTheme);
    if (newTheme === 'system') document.documentElement.removeAttribute('data-theme');
    else document.documentElement.setAttribute('data-theme', newTheme);
  }

  return (
    <button onClick={() => applyTheme(theme === 'dark' ? 'light' : 'dark')}
      aria-label={`Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`}>
      {theme === 'dark' ? 'Light mode' : 'Dark mode'}
    </button>
  );
}

防止深色模式闪烁(在渲染前应用):


<script>
  (function() {
    var theme = localStorage.getItem('theme');
    if (theme === 'dark' || (!theme && matchMedia('(prefers-color-scheme: dark)').matches))
      document.documentElement.setAttribute('data-theme', 'dark');
  })();
</script>

多租户白标(在服务端注入各租户的覆盖值):

// In your server response, inject tenant CSS overrides in <head>
// so they're applied before the page renders (no flash)
const tenantTheme = await getTenantTheme(req.hostname);
const cssOverrides = tenantTheme
  ? `:root { ${Object.entries(tenantTheme)
      .map(([k, v]) => `--${k}: ${sanitizeCssValue(v)};`)
      .join(' ')} }`
  : '';

// Sanitize to allow only safe CSS value patterns
function sanitizeCssValue(value) {
  if (/^#[0-9a-fA-F]{3,8}$/.test(value)) return value; // hex color
  if (/^\d+(\.\d+)?(px|rem|em|%)$/.test(value)) return value; // length
  if (/^[a-zA-Z0-9\s,'"]+$/.test(value)) return value; // font names
  return ''; // reject everything else (prevents CSS injection)
}
步骤 3:为团队构建令牌参考文档

无论使用哪种平台,都要记录令牌,确保设计师和开发者保持同步:

  • Shopify: 主题编辑器可作为实时令牌参考 — 将 Customize URL 分享给设计团队
  • WooCommerce: 在 Storybook 实例或简单的 HTML 参考页面中记录 CSS 变量名称
  • BigCommerce: Cornerstone 的 config.json 会记录可用设置;在 SCSS 文件中添加注释
  • 自定义: 使用 Style Dictionary 生成静态令牌文档页面,或在 Storybook 中记录

最佳实践

  • 切勿在组件 CSS 中硬编码颜色 — 始终使用语义化令牌;避免因品牌重塑而需要全局查找并替换 #2563eb
  • 语义化令牌名称应体现含义 — 使用 --color-brand-primary,而非 --color-blue-600;十六进制值会改变,但含义不变
  • 使用真实设备测试深色模式 — macOS/iOS 和 Windows 的默认深色模式行为不同;两者都要测试
  • 验证对比度 — 设置品牌颜色后,使用 WebAIM Contrast Checker 验证 WCAG 对比度(正文文本为 4.5:1)
  • 清理白标 CSS 注入内容 — 只允许十六进制颜色、rem/px 长度值和字体名称;拒绝任意字符串,以防止 CSS 注入攻击

常见问题

问题解决方案
深色模式导致无样式内容闪烁在样式表加载前,于 <head> 脚本中同步应用 data-theme 属性
首次渲染时未应用租户主题覆盖在服务端将租户 CSS 注入内联 <style> 标签;不要在 useEffect 中应用
Figma 与代码中的设计令牌不同步使用 Figma 插件 Tokens Studio,直接导出到 CSS 变量 / theme.json 文件
白标 CSS 导致 XSS清理租户令牌值,仅允许有效的 CSS 颜色、长度和 font-family 格式
品牌重塑需要修改许多文件如果你发现自己要替换多个组件文件中的颜色,说明你跳过了语义化令牌层 — 请先重构为语义化令牌

相关技能

  • @responsive-storefront
  • @accessibility-commerce
  • @mega-menu-builder
  • @product-page-design

评论

支持 Markdown