颜色主题开发基础
颜色主题决定 VS Code 的"长相":编辑器的背景色、关键字的高亮色、侧边栏的明暗层次。主题插件结构简单,但配色设计是门艺术。
主题是什么
颜色主题是一份 JSON 文件,定义三类颜色:
| 区域 | 作用 |
|---|---|
colors | Workbench UI 颜色(编辑器背景、标题栏、状态栏等) |
tokenColors | 代码 Token 着色(关键字、字符串、函数名的语法高亮) |
semanticTokenColors | 语义 Token 着色(基于语言理解的符号类型着色) |
注册颜色主题
package.json 中通过 contributes.themes 声明:
{
"contributes": {
"themes": [
{
"label": "MyOcean Dark",
"uiTheme": "vs-dark",
"path": "./themes/my-ocean-dark.json"
},
{
"label": "MyOcean Light",
"uiTheme": "vs",
"path": "./themes/my-ocean-light.json"
},
{
"label": "MyOcean High Contrast",
"uiTheme": "hc-black",
"path": "./themes/my-ocean-hc.json"
}
]
}
}| 字段 | 说明 |
|---|---|
label | 主题显示名称 |
uiTheme | 基础主题类型,决定 UI 组件默认配色 |
path | 主题 JSON 文件路径 |
uiTheme 主题类型
uiTheme 对应 VS Code 的四类基础主题:
| 值 | 含义 | 适用 |
|---|---|---|
vs | 亮色主题 | 白色/浅灰背景 |
vs-dark | 暗色主题 | 深色背景 |
hc-black | 高对比度暗色 | 无障碍高对比 |
hc-light | 高对比度亮色 | 无障碍高对比亮色 |
uiTheme 只决定"基底":你声明 vs-dark 时,UI 组件会继承暗色默认值,再被你的 colors 覆盖。主题 JSON 中还有个 type 字段,控制代码编辑器的默认语法高亮配色:
{
"name": "MyOcean Dark",
"type": "dark",
"colors": {
"editor.background": "#0d1117"
}
}type 可取 dark、light、highContrast,决定默认语法高亮的明暗基底。它和 uiTheme 应保持一致的明暗取向。
JSON 主题文件结构
完整的主题文件由四部分构成:
{
"name": "MyOcean Dark",
"type": "dark",
"colors": {
"editor.background": "#0d1117",
"editor.foreground": "#c9d1d9",
"editor.lineHighlightBackground": "#161b22"
},
"tokenColors": [
{
"scope": ["keyword", "storage.type"],
"settings": { "foreground": "#ff7b72" }
}
],
"semanticTokenColors": {
"parameter": "#79c0ff"
},
"semanticHighlighting": true
}四部分职责
| 部分 | 内容 | 作用 |
|---|---|---|
name / type | 元数据 | 主题名与明暗类型 |
colors | 键值对 | Workbench UI 颜色 |
tokenColors | 规则数组 | 语法高亮(TextMate 规则) |
semanticTokenColors | 键值对 | 语义着色 |
colors 常用键
Workbench 颜色键按 UI 组件前缀分组,先掌握高频键:
{
"colors": {
"editor.background": "#0d1117",
"editor.foreground": "#c9d1d9",
"editorLineNumber.foreground": "#6e7681",
"editor.selectionBackground": "#264f78",
"editor.lineHighlightBackground": "#161b22",
"editorIndentGuide.background": "#21262d",
"editorCursor.foreground": "#58a6ff",
"sideBar.background": "#010409",
"sideBar.foreground": "#c9d1d9",
"titleBar.activeBackground": "#010409",
"statusBar.background": "#010409",
"activityBar.background": "#010409",
"tab.activeBackground": "#0d1117",
"tab.inactiveBackground": "#010409",
"list.hoverBackground": "#161b22",
"list.activeSelectionBackground": "#1f6feb",
"input.background": "#010409",
"button.background": "#238636"
}
}分组速览
| 前缀 | 覆盖区域 |
|---|---|
editor.* | 编辑器本体 |
editorLineNumber.* | 行号 |
editorGutter.* | 装订区(断点/折叠) |
sideBar.* | 侧边栏 |
titleBar.* | 标题栏 |
statusBar.* | 状态栏 |
activityBar.* | 活动栏(最左侧图标栏) |
tab.* | 编辑器标签页 |
list.* | 列表(资源管理器、快速选择) |
input.* | 输入框 |
button.* | 按钮 |
menu.* | 菜单 |
tokenColors 语法着色
tokenColors 定义语法高亮规则,基于 TextMate scope:
{
"tokenColors": [
{
"name": "关键字",
"scope": "keyword",
"settings": { "foreground": "#ff7b72" }
},
{
"name": "字符串",
"scope": "string",
"settings": { "foreground": "#a5d6ff" }
},
{
"name": "注释",
"scope": "comment",
"settings": { "foreground": "#8b949e", "fontStyle": "italic" }
},
{
"name": "函数名",
"scope": "entity.name.function",
"settings": { "foreground": "#d2a8ff" }
}
]
}scope 层级
scope 采用层级结构,规则按从宽到窄匹配:
| 层级 | 示例 | 范围 |
|---|---|---|
| 类别 | keyword | 所有关键字 |
| 细分 | keyword.control | 控制关键字(if/for/return) |
| 精确 | keyword.control.conditional | 条件关键字 |
规则数组按顺序匹配,越靠后的精确规则覆盖前面的宽规则。常用 scope: "keyword.operator" 可同时匹配多个 scope 名:
{
"scope": ["keyword.operator", "punctuation.definition.keyword"],
"settings": { "foreground": "#79c0ff" }
}semanticTokenColors 语义着色
语义着色基于语言服务对代码的理解(变量、参数、类型),比 TextMate 语法更准确:
{
"semanticTokenColors": {
"parameter": "#79c0ff",
"variable": "#ffa657",
"property": "#79c0ff",
"type": "#d2a8ff",
"namespace": "#d2a8ff",
"function": "#d2a8ff",
"number": "#79c0ff"
}
}修饰符
语义 token 可带修饰符,用 . 连接:
{
"semanticTokenColors": {
"variable.readonly": "#ffa657",
"variable.defaultLibrary": "#8b949e",
"property.readonly": "#79c0ff"
}
}关闭语义着色
{
"semanticTokenColors": {},
"semanticHighlighting": false
}workbench.colorCustomizations 覆盖
用户可以在设置中覆盖任意主题颜色,无需改主题文件:
{
"workbench.colorCustomizations": {
"editor.background": "#1e1e2e",
"[MyOcean Dark]": {
"editor.background": "#0d1117"
}
}
}[主题名] 语法让覆盖只对特定主题生效。主题作者也可以读取此设置做调试参考,但通常不需要在插件中处理它——这是用户的自由空间。
主题文件校验
开发时用命令面板校验主题:
命令面板 → Developer: Inspect Editor Tokens and Scopes这个命令显示光标处 Token 的 scope 与颜色来源,是调试 tokenColors 的核心工具:
------ Inspect Token at 5:13 -----
Text: for
Scope: keyword.control
Foreground: #ff7b72颜色来源会标注"来自主题文件的哪条规则",方便定位覆盖链。
主题最小示例
一个可运行的暗色主题:
{
"name": "Minimal Dark",
"type": "dark",
"colors": {
"editor.background": "#16181d",
"editor.foreground": "#e6e6e6",
"editorLineNumber.foreground": "#5c5c5c",
"editor.selectionBackground": "#3a3d41",
"editor.lineHighlightBackground": "#1c1e24"
},
"tokenColors": [
{ "scope": "comment", "settings": { "foreground": "#7d8590", "fontStyle": "italic" } },
{ "scope": "string", "settings": { "foreground": "#9ece6a" } },
{ "scope": "keyword", "settings": { "foreground": "#bb9af7" } },
{ "scope": "entity.name.function", "settings": { "foreground": "#7aa2f7" } },
{ "scope": "constant.numeric", "settings": { "foreground": "#ff9e64" } }
]
}保存后在主题选择器(Ctrl+K Ctrl+T)中选择 "Minimal Dark" 即可预览。
主题的基础框架就是一份 JSON:colors 管 UI、tokenColors 管语法、semanticTokenColors 管语义。下一步深入 Workbench 各组件颜色键的完整体系。