起因:一个被忽视的原生能力
作为 Obsidian 的重度用户,Mermaid 已经成为我日常笔记中不可或缺的一部分。用纯文本快速画出流程图、时序图,这种体验确实很爽。
但用久了就会发现一个问题:所有图表都长得一模一样。
当我想给不同类型的笔记配上不同风格的图表时,比如项目文档用商务风格、技术笔记用深色主题、学习笔记用清新配色,我发现这个看似简单的需求,实现起来居然异常困难。
网上能找到的方案基本只有两条路:
- 写
custom.css,全局覆盖 Mermaid 样式 - 安装第三方主题插件
前者的问题是影响范围太大,一改全改;后者则是依赖插件维护者的更新频率,很多插件早已停止维护。
我本来打算自己写个插件来解决这个问题。但在研究 Mermaid 的 API 文档时,我无意中发现了一个藏得很深的特性:Directives(配置指令)。
它允许你在 Mermaid 代码块的开头,用一行特殊格式的注释来控制单个图表的主题和样式。不需要插件,不需要全局配置,就在代码块里,直接生效。
我试了一下,发现在 Obsidian 中完全可用。
更让我惊讶的是:我问了身边很多 Obsidian 重度用户,都没有一个人知道这个功能。
翻遍 Obsidian 的官方文档,没有提及;Mermaid 的文档虽然有写,但藏在配置章节的深处,很容易被忽略。这么好用的原生能力,就这样被埋没了。
所以我决定写这篇文章,把这个"隐藏开关"分享出来。
什么是 Directives?
在 Mermaid 中,%% 开头的内容通常是注释。但如果你用特定的 JSON 格式书写,Mermaid 的渲染引擎会将其识别为配置指令(Directive)。
它的作用就像是写在图表开头的"样式配置文件"——每个图表可以有自己独立的主题,互不干扰。
这意味着:
- 同一个笔记里,不同的图表可以有不同的配色
- 不需要写 CSS,不需要装插件
- 配置跟着代码走,复制粘贴到其他地方依然生效
这才是 Mermaid 在 Obsidian 中的正确打开方式。
下面我会按照实际使用场景,分享几种最实用的配置方式。
用法 1:一键切换主题
Mermaid 内置了 5 个主题风格:
default— 经典蓝色(默认)neutral— 极简黑白灰,适合打印dark— 深色模式forest— 清新绿色base— 基础主题,可完全自定义
你只需要在 Mermaid 代码块的第一行加上这句:
%%{init: {'theme': 'forest'}}%%
graph TD
A[开始] --> B{是否满意?}
B -->|是| C[完成]
B -->|否| D[调整主题]
| |
就这么简单。图表会立刻变成森林主题的绿色风格。
试试把 'forest' 改成 'neutral',你会得到一个非常适合商务文档和打印的极简配色。
用法 2:自定义配色方案
如果内置主题还不够,你可以通过 themeVariables 精确控制每一种颜色。注意:只有 base 主题才支持自定义。
基础配色示例
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffcc00',
'primaryTextColor': '#333',
'primaryBorderColor': '#333',
'lineColor': '#ff6b6b'
}
}
}%%
graph LR
A[自定义黄色节点] --> B[红色连线]
| |
核心主题变量说明
根据官方文档,以下是最常用的主题变量:
| 变量名 | 默认值 | 说明 |
|---|---|---|
primaryColor | #fff4dd | 主要节点背景色 |
primaryTextColor | 自动计算 | 主要节点文字颜色 |
primaryBorderColor | 自动计算 | 主要节点边框颜色 |
secondaryColor | 自动计算 | 次要元素颜色 |
tertiaryColor | 自动计算 | 第三级元素颜色 |
lineColor | 自动计算 | 连线颜色 |
textColor | 自动计算 | 一般文字颜色 |
background | #f4f4f4 | 背景色 |
mainBkg | 自动计算 | 主要形状背景色 |
fontFamily | trebuchet ms, verdana, arial | 字体 |
fontSize | 16px | 字号 |
用法 3:深色模式适配
如果你的 Obsidian 使用深色主题,可以启用 darkMode 选项,让 Mermaid 自动调整派生颜色的计算方式:
%%{
init: {
'theme': 'base',
'themeVariables': {
'darkMode': true,
'primaryColor': '#1e40af',
'primaryTextColor': '#e0e7ff',
'lineColor': '#60a5fa',
'background': '#1e1e1e'
}
}
}%%
graph TD
A[深色主题] --> B[自动计算对比度]
B --> C[阅读更舒适]
| |
darkMode: true 会影响所有自动计算的派生颜色,确保在深色背景下有足够的对比度。
用法 4:流程图专属配置
流程图有一些专属的主题变量,可以更精细地控制子图、节点和连线的样式:
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#e3f2fd',
'clusterBkg': '#fff3e0',
'clusterBorder': '#ff9800',
'defaultLinkColor': '#1976d2',
'edgeLabelBackground': '#ffffff'
}
}
}%%
graph TD
subgraph 子图区域
A[节点A] --> B[节点B]
end
B --> C[节点C]
| |
流程图专属变量:
clusterBkg— 子图背景色clusterBorder— 子图边框色defaultLinkColor— 连线颜色edgeLabelBackground— 连线标签背景色nodeTextColor— 节点文字颜色
用法 5:时序图配色
时序图也有自己的专属变量,可以精确控制角色框、信号线和激活框的颜色:
%%{
init: {
'theme': 'base',
'themeVariables': {
'actorBkg': '#e8f5e9',
'actorBorder': '#4caf50',
'actorTextColor': '#1b5e20',
'signalColor': '#ff5722',
'signalTextColor': '#d84315',
'activationBkgColor': '#fff3e0',
'activationBorderColor': '#ff9800'
}
}
}%%
sequenceDiagram
participant A as 用户
participant B as 系统
A->>B: 发送请求
activate B
B-->>A: 返回结果
deactivate B
| |
时序图专属变量:
actorBkg— 角色框背景actorBorder— 角色框边框actorTextColor— 角色文字颜色signalColor— 信号线颜色signalTextColor— 信号文字颜色activationBkgColor— 激活框背景activationBorderColor— 激活框边框
用法 6:饼图专属配置
饼图可以自定义每个扇形的颜色,以及标题和图例的样式:
%%{
init: {
'theme': 'base',
'themeVariables': {
'pie1': '#ff6b6b',
'pie2': '#4ecdc4',
'pie3': '#45b7d1',
'pie4': '#ffa07a',
'pieTitleTextSize': '28px',
'pieTitleTextColor': '#2c3e50',
'pieStrokeColor': '#ffffff',
'pieStrokeWidth': '3px'
}
}
}%%
pie title 2024年项目分布
"项目A" : 35
"项目B" : 25
"项目C" : 20
"项目D" : 20
| |
饼图专属变量:
pie1到pie12— 每个扇形的颜色pieTitleTextSize/pieTitleTextColor— 标题样式pieSectionTextSize/pieSectionTextColor— 扇形标签样式pieStrokeColor/pieStrokeWidth— 扇形边框pieOpacity— 扇形透明度
用法 7:甘特图配色
甘特图虽然没有在文档中单独列出变量,但可以通过通用变量来控制:
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#3498db',
'secondaryColor': '#2ecc71',
'tertiaryColor': '#e74c3c',
'primaryTextColor': '#fff'
}
}
}%%
gantt
title 项目进度表
dateFormat YYYY-MM-DD
section 阶段一
任务1 :done, des1, 2024-01-01,2024-01-10
任务2 :active, des2, 2024-01-11,2024-01-20
section 阶段二
任务3 : des3, 2024-01-21,2024-02-01
| |
实用配色方案推荐
方案1:清新商务风
| |
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#e3f2fd',
'primaryTextColor': '#1565c0',
'primaryBorderColor': '#1976d2',
'lineColor': '#42a5f5',
'secondaryColor': '#f3e5f5',
'tertiaryColor': '#fff3e0'
}
}
}%%
sequenceDiagram
participant Client as 客户端
participant User as 资源所有者 (用户)
participant AuthServer as 授权服务器
participant ResourceServer as 资源服务器
User->>Client: 1. 请求访问受保护资源
Client->>Client: 2. 生成授权请求URL
Client->>User: 3. 将用户重定向到授权服务器
User->>AuthServer: 4. 登录并同意授权
AuthServer->>AuthServer: 5. 生成授权码 (Authorization Code)
AuthServer->>Client: 6. 重定向回客户端,并附带授权码
Client->>Client: 7. 从重定向URL中解析授权码
Client->>AuthServer: 8. 使用授权码和客户端凭证请求访问令牌
AuthServer->>AuthServer: 9. 验证授权码和客户端凭证
AuthServer->>Client: 10. 颁发访问令牌 (Access Token)
Client->>Client: 11. 存储访问令牌
Client->>ResourceServer: 12. 使用访问令牌请求受保护资源
ResourceServer->>ResourceServer: 13. 验证访问令牌有效性
ResourceServer->>Client: 14. 返回受保护资源
方案2:温暖橙色调
| |
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#fff4e6',
'primaryTextColor': '#d84315',
'primaryBorderColor': '#f57c00',
'lineColor': '#ff6f00',
'secondaryColor': '#ffe0b2'
}
}
}%%
sequenceDiagram
participant Client as 客户端
participant User as 资源所有者 (用户)
participant AuthServer as 授权服务器
participant ResourceServer as 资源服务器
User->>Client: 1. 请求访问受保护资源
Client->>Client: 2. 生成授权请求URL
Client->>User: 3. 将用户重定向到授权服务器
User->>AuthServer: 4. 登录并同意授权
AuthServer->>AuthServer: 5. 生成授权码 (Authorization Code)
AuthServer->>Client: 6. 重定向回客户端,并附带授权码
Client->>Client: 7. 从重定向URL中解析授权码
Client->>AuthServer: 8. 使用授权码和客户端凭证请求访问令牌
AuthServer->>AuthServer: 9. 验证授权码和客户端凭证
AuthServer->>Client: 10. 颁发访问令牌 (Access Token)
Client->>Client: 11. 存储访问令牌
Client->>ResourceServer: 12. 使用访问令牌请求受保护资源
ResourceServer->>ResourceServer: 13. 验证访问令牌有效性
ResourceServer->>Client: 14. 返回受保护资源
注意事项
- 只有
base主题支持自定义:其他四个主题(default、neutral、dark、forest)是预设的,无法通过themeVariables修改。 - 颜色格式必须是十六进制:使用
#ff0000而不是red,否则不会生效。 - 很多变量会自动计算:比如
primaryBorderColor会从primaryColor自动派生。如果你想完全控制,需要显式指定每个变量。 - 不同图表类型有不同的专属变量:流程图、时序图、饼图等都有自己独特的可配置项。