LSP Server 插件:9种官方语言服务器集成与自定义 LSP 配置
第五十三章:主题与外观插件:CSS 变量、Dark Mode 与品牌定制
53.1 外观插件的定位与价值
Claude Code 是一个以文本为核心的工具,但视觉体验对生产力的影响不可忽视。长时间使用默认主题会造成视觉疲劳;企业用户需要将工具的外观与品牌视觉系统对齐;不同的工作环境(白天/黑夜、高对比度需求、色盲友好模式)需要不同的色彩方案。
外观 Plugin(Theme Plugin)解决的就是这一类需求。它通过向 Claude Code 注入 CSS 变量和样式覆盖,在不修改核心代码的前提下实现深度的视觉定制。
与功能型 Plugin 不同,外观 Plugin 通常:
- 不包含 MCP Server(无工具调用)
- 不包含 Hooks(无生命周期注入)
- 不需要
network:outbound权限 - 核心内容是 CSS 文件和
theme.json配置
53.2 Claude Code 的 CSS 变量系统
变量分层架构
Claude Code 的样式系统基于 CSS 自定义属性(CSS Custom Properties,即 CSS 变量)构建,分为三个层次:
基础令牌(Base Tokens)
├── 原始色值(如 --cc-color-blue-500: #3B82F6)
└── 原始尺寸(如 --cc-spacing-4: 16px)
语义令牌(Semantic Tokens)
├── 功能色(如 --cc-color-primary: var(--cc-color-blue-500))
└── 角色色(如 --cc-color-text-primary: #1a1a1a)
组件令牌(Component Tokens)
├── 按钮(如 --cc-button-bg: var(--cc-color-primary))
└── 输入框(如 --cc-input-border: var(--cc-color-border))
主题 Plugin 主要操作语义令牌层,偶尔调整组件令牌。直接修改基础令牌会影响范围过大,容易破坏视觉一致性。
核心语义变量完整列表
/* === 文字颜色 === */
--cc-color-text-primary /* 主要文字 */
--cc-color-text-secondary /* 次要文字(注释、标签) */
--cc-color-text-tertiary /* 三级文字(占位符、禁用状态) */
--cc-color-text-inverse /* 反色文字(深色背景上的白字) */
--cc-color-text-accent /* 强调文字(链接、高亮) */
--cc-color-text-error /* 错误文字 */
--cc-color-text-success /* 成功文字 */
--cc-color-text-warning /* 警告文字 */
/* === 背景颜色 === */
--cc-color-bg-primary /* 主背景 */
--cc-color-bg-secondary /* 次级背景(侧边栏、面板) */
--cc-color-bg-tertiary /* 三级背景(卡片、弹窗) */
--cc-color-bg-elevated /* 浮起背景(下拉菜单、tooltip) */
--cc-color-bg-hover /* 悬停状态背景 */
--cc-color-bg-active /* 激活状态背景 */
--cc-color-bg-code /* 代码块背景 */
/* === 边框颜色 === */
--cc-color-border /* 默认边框 */
--cc-color-border-strong /* 强调边框 */
--cc-color-border-focus /* 焦点边框(聚焦状态) */
/* === 功能色 === */
--cc-color-primary /* 品牌主色(按钮、链接) */
--cc-color-primary-hover /* 主色悬停态 */
--cc-color-primary-active /* 主色激活态 */
/* === 代码高亮 === */
--cc-syntax-keyword /* 关键字 */
--cc-syntax-string /* 字符串 */
--cc-syntax-comment /* 注释 */
--cc-syntax-number /* 数字 */
--cc-syntax-function /* 函数名 */
--cc-syntax-variable /* 变量名 */
--cc-syntax-operator /* 运算符 */
--cc-syntax-type /* 类型名 */
/* === 字体排版 === */
--cc-font-family-sans /* 无衬线字体 */
--cc-font-family-mono /* 等宽字体(代码) */
--cc-font-size-base /* 基础字号 */
--cc-line-height-base /* 基础行高 */
/* === 间距与圆角 === */
--cc-radius-sm /* 小圆角 */
--cc-radius-md /* 中圆角 */
--cc-radius-lg /* 大圆角 */
53.3 Theme Plugin 项目结构
my-theme-plugin/
├── plugin.json
├── themes/
│ ├── light.css ← 浅色主题变量
│ ├── dark.css ← 深色主题变量
│ └── high-contrast.css ← 高对比度变量
├── theme.json ← 主题元数据和注册信息
├── preview/
│ ├── light.png ← 浅色主题预览图(市场展示用)
│ └── dark.png ← 深色主题预览图
└── README.md
plugin.json(主题专用字段)
{
"name": "acme-brand-theme",
"version": "1.0.0",
"description": "ACME Corporation brand theme for Claude Code",
"author": "ACME Design Team <[email protected]>",
"license": "MIT",
"keywords": ["theme", "brand", "corporate"],
"type": "theme",
"theme": {
"variants": [
{
"id": "acme-light",
"name": "ACME Light",
"appearance": "light",
"stylesheet": "./themes/light.css"
},
{
"id": "acme-dark",
"name": "ACME Dark",
"appearance": "dark",
"stylesheet": "./themes/dark.css"
},
{
"id": "acme-high-contrast",
"name": "ACME High Contrast",
"appearance": "dark",
"stylesheet": "./themes/high-contrast.css",
"tags": ["accessibility", "high-contrast"]
}
],
"defaultVariant": "acme-light",
"previewImages": {
"acme-light": "./preview/light.png",
"acme-dark": "./preview/dark.png"
}
},
"engines": {
"claude-code": ">=1.0.0"
},
"permissions": []
}
注意 type: "theme" 声明——这告诉 Claude Code 这是一个纯外观 Plugin,不需要启动任何子进程。
53.4 编写主题 CSS
浅色主题示例
/* themes/light.css */
/* ACME Brand Light Theme */
:root[data-theme="acme-light"] {
/* === 品牌色系 === */
/* ACME 品牌主色:深海蓝 */
--cc-color-primary: #0047AB;
--cc-color-primary-hover: #003580;
--cc-color-primary-active: #002460;
/* === 背景色系 === */
--cc-color-bg-primary: #FFFFFF;
--cc-color-bg-secondary: #F5F7FA;
--cc-color-bg-tertiary: #EDF0F5;
--cc-color-bg-elevated: #FFFFFF;
--cc-color-bg-hover: rgba(0, 71, 171, 0.06);
--cc-color-bg-active: rgba(0, 71, 171, 0.12);
--cc-color-bg-code: #F8F9FC;
/* === 文字色系 === */
--cc-color-text-primary: #1A1D23;
--cc-color-text-secondary: #4B5568;
--cc-color-text-tertiary: #9AA5B4;
--cc-color-text-inverse: #FFFFFF;
--cc-color-text-accent: #0047AB;
/* === 边框色系 === */
--cc-color-border: #D1D9E6;
--cc-color-border-strong: #A8B4C8;
--cc-color-border-focus: #0047AB;
/* === 状态色 === */
--cc-color-text-error: #C0392B;
--cc-color-text-success: #1A7340;
--cc-color-text-warning: #C17D00;
/* === 代码语法高亮 === */
--cc-syntax-keyword: #0047AB;
--cc-syntax-string: #1A7340;
--cc-syntax-comment: #9AA5B4;
--cc-syntax-number: #C17D00;
--cc-syntax-function: #6B3FA0;
--cc-syntax-variable: #1A1D23;
--cc-syntax-operator: #4B5568;
--cc-syntax-type: #B83C1E;
/* === 字体 === */
--cc-font-family-sans: 'Inter', 'SF Pro Display', -apple-system, sans-serif;
--cc-font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
--cc-font-size-base: 14px;
--cc-line-height-base: 1.6;
/* === 圆角 === */
--cc-radius-sm: 4px;
--cc-radius-md: 6px;
--cc-radius-lg: 12px;
}
深色主题示例
/* themes/dark.css */
/* ACME Brand Dark Theme */
:root[data-theme="acme-dark"] {
/* === 品牌色系(深色模式下适当调亮) === */
--cc-color-primary: #4D9FFF;
--cc-color-primary-hover: #6FB3FF;
--cc-color-primary-active: #91C5FF;
/* === 背景色系 === */
--cc-color-bg-primary: #0D1117;
--cc-color-bg-secondary: #161B22;
--cc-color-bg-tertiary: #21262D;
--cc-color-bg-elevated: #2D333B;
--cc-color-bg-hover: rgba(77, 159, 255, 0.08);
--cc-color-bg-active: rgba(77, 159, 255, 0.16);
--cc-color-bg-code: #161B22;
/* === 文字色系 === */
--cc-color-text-primary: #E6EDF3;
--cc-color-text-secondary: #8B949E;
--cc-color-text-tertiary: #484F58;
--cc-color-text-inverse: #0D1117;
--cc-color-text-accent: #4D9FFF;
/* === 边框色系 === */
--cc-color-border: #30363D;
--cc-color-border-strong: #484F58;
--cc-color-border-focus: #4D9FFF;
/* === 状态色 === */
--cc-color-text-error: #F85149;
--cc-color-text-success: #3FB950;
--cc-color-text-warning: #D29922;
/* === 代码语法高亮 === */
--cc-syntax-keyword: #FF7B72;
--cc-syntax-string: #A5D6FF;
--cc-syntax-comment: #8B949E;
--cc-syntax-number: #F2CC60;
--cc-syntax-function: #D2A8FF;
--cc-syntax-variable: #E6EDF3;
--cc-syntax-operator: #8B949E;
--cc-syntax-type: #FFA657;
}
高对比度主题
高对比度主题的设计原则与普通主题有所不同——可读性优先,美观性次之:
/* themes/high-contrast.css */
:root[data-theme="acme-high-contrast"] {
/* 背景:纯黑 */
--cc-color-bg-primary: #000000;
--cc-color-bg-secondary: #0A0A0A;
--cc-color-bg-code: #000000;
/* 文字:纯白,确保 WCAG AAA 对比度 */
--cc-color-text-primary: #FFFFFF;
--cc-color-text-secondary: #E0E0E0;
--cc-color-text-tertiary: #B0B0B0;
/* 主色:亮黄,最高可见度 */
--cc-color-primary: #FFD700;
--cc-color-primary-hover: #FFEA00;
--cc-color-text-accent: #FFD700;
/* 边框:清晰可见 */
--cc-color-border: #808080;
--cc-color-border-strong: #C0C0C0;
--cc-color-border-focus: #FFD700;
/* 状态色:高饱和度确保可区分 */
--cc-color-text-error: #FF4444;
--cc-color-text-success: #00FF88;
--cc-color-text-warning: #FFAA00;
/* 增大字号确保可读性 */
--cc-font-size-base: 15px;
--cc-line-height-base: 1.8;
}
53.5 Dark Mode 自动切换机制
跟随系统偏好
Claude Code 支持自动跟随系统的 Dark Mode 设置。在 theme.json 中配置自动切换规则:
{
"autoSwitch": {
"enabled": true,
"lightVariant": "acme-light",
"darkVariant": "acme-dark"
}
}
启用后,Claude Code 会监听 prefers-color-scheme 媒体查询,当系统切换深/浅色模式时自动切换对应的主题变量。
用户手动切换
即使启用了自动切换,用户也可以手动锁定某个主题:
# 手动设置主题
claude config set theme acme-dark
# 切换回自动模式
claude config set theme auto
53.6 字体定制
内置字体与外部字体
主题 Plugin 可以使用两类字体:
内置字体:Claude Code 内置了常见的等宽字体(JetBrains Mono、Fira Code、Cascadia Code)和无衬线字体(Inter、SF Pro)。直接在 CSS 变量中引用即可。
外部字体:如果你的品牌字体不在内置列表中,需要在 plugin.json 中声明字体资源:
{
"theme": {
"fonts": [
{
"family": "ACME Sans",
"sources": [
{
"url": "./fonts/ACMESans-Regular.woff2",
"weight": 400,
"style": "normal"
},
{
"url": "./fonts/ACMESans-Bold.woff2",
"weight": 700,
"style": "normal"
}
]
}
]
}
}
字体文件放在 Plugin 包中,Claude Code 会在加载主题时自动注册这些字体。
代码等宽字体的特殊性
代码编辑区域的等宽字体选择对开发者体验影响显著。几个实践建议:
/* 建议:提供字体降级栈 */
--cc-font-family-mono:
'JetBrains Mono', /* 首选:连字支持,开发者友好 */
'Fira Code', /* 备选:开源,跨平台一致 */
'Cascadia Code', /* Windows 备选 */
'SF Mono', /* macOS 系统备选 */
'Consolas', /* Windows 系统备选 */
monospace; /* 最终降级 */
/* 启用连字(如果字体支持) */
font-feature-settings: "liga" 1, "calt" 1;
53.7 组件级定制
对于标准 CSS 变量无法覆盖的定制需求,主题 Plugin 支持组件级别的 CSS 覆盖:
/* themes/light.css 末尾追加 */
/* 定制侧边栏宽度 */
.cc-sidebar {
width: 280px;
}
/* 定制对话气泡样式 */
.cc-message-bubble--assistant {
border-left: 3px solid var(--cc-color-primary);
border-radius: 0 var(--cc-radius-md) var(--cc-radius-md) 0;
}
/* 定制工具调用展示卡片 */
.cc-tool-call-card {
background: var(--cc-color-bg-code);
border: 1px solid var(--cc-color-border);
font-family: var(--cc-font-family-mono);
font-size: 12px;
}
使用组件级定制时需要注意:Claude Code 的内部 CSS 类名可能在版本升级时发生变化,建议在 plugin.json 的 engines.claude-code 中声明精确的版本范围,并在升级后测试样式兼容性。
53.8 主题预览图规范
市场展示页面会显示主题预览图,直接影响用户的安装决策。预览图规范:
尺寸:1280 × 800 像素(16:10 比例)
格式:PNG,JPEG 或 WebP(建议 PNG 保留细节)
最大文件大小:500 KB
内容要求:
├── 展示对话界面(包含用户消息和 Claude 回复)
├── 展示代码块(体现语法高亮色彩)
├── 展示侧边栏(体现整体布局和色调)
└── 不可包含真实的个人信息或企业机密内容
53.9 主题的可访问性验证
发布前必须验证主题的可访问性。WCAG 2.1 AA 标准要求:
- 普通文字:对比度 ≥ 4.5:1
- 大文字(18px 粗体或 24px 普通):对比度 ≥ 3:1
- 交互组件边框:对比度 ≥ 3:1
# 使用内置可访问性检查工具
claude-plugin theme check-accessibility ./themes/light.css
# 输出示例:
# Checking accessibility for acme-light theme...
# ✓ --cc-color-text-primary on --cc-color-bg-primary: 12.4:1 (AAA)
# ✓ --cc-color-text-secondary on --cc-color-bg-primary: 5.2:1 (AA)
# ✗ --cc-color-text-tertiary on --cc-color-bg-primary: 2.8:1 (FAIL)
# ↳ Required: 4.5:1 for normal text
# ↳ Suggestion: Darken --cc-color-text-tertiary to #767676 or darker
所有 AA 级别不通过的对比度组合都会导致市场审核失败。
小结
主题 Plugin 通过 CSS 变量系统实现非侵入式的视觉定制,其核心是理解 Claude Code 的三层变量体系(基础令牌 → 语义令牌 → 组件令牌)并优先操作语义层。深色模式自动切换、自定义字体、高对比度可访问性支持是高质量主题 Plugin 的必备特性。发布前的可访问性验证不只是审核要求,也是对所有用户的基本尊重。下一章转向技术深度更高的 LSP Plugin 开发。