首页 › 指南 › Mermaid 甘特图:语法、坑,以及与可视化编辑器的往返

Mermaid 甘特图:语法、坑,以及与可视化编辑器的往返

Mermaid 的 gantt 代码块在 GitHub、GitLab、Notion 和 Obsidian 里都能原生渲染,这让它成为把进度计划放到工作现场最省事的方式。它同时也极其难改:动一个日期,下游每一条 after 链都得手工重新推算。本文讲语法、讲坑,也讲那个缺失的环节, , 可视化编辑之后把代码取回来。

作者 Uttam Regmi更新于 2026年7月19日3 分钟阅读

本页内容
  1. 一次过完语法
  2. 一段可以直接贴进 README 的例子
  3. 任务行字段速查
  4. 四个一定会咬你的地方
  5. Mermaid 表达不了的东西
  6. 可视化编辑,再把代码粘回去
同一份进度计划,代码形态与横条形态:
gantt section 阶段 任务 :a, 5d 任务 :after a, 8d文本图表

一次过完语法

一个 gantt 代码块以 gantt 加几行头部声明开始,然后是 section 标题,标题下面是任务行。

一行任务是名称、一个冒号,然后是逗号分隔的字段:

Task name :tag, id, start, duration

值得记住的头部声明:dateFormat(你的文件里日期是怎么写的)、excludes weekends(跳过周六和周日)、title,以及 axisFormat(坐标轴标签怎么显示,用的是 strftime 风格的占位符)。缩进只是书写习惯,不是语法的一部分。字段是按形状识别的,不严格看位置,所以 :done, res, 2026-01-05, 5d 和 :res, done, 2026-01-05, 5d 都能解析。

任务 A:标识 a1:2026-03-02:5d任务标识开始工期
一行 Mermaid 任务上的每一个字段,以及哪些可以省略。

一段可以直接贴进 README 的例子

一个完整可用的代码块,描述一件真实的工作:把面向公众的接口从 v1 迁到 v2,同时上线小程序 2.0。它用到了 section、绝对日期、after 链、全部四个标签、一个里程碑,以及排除周末和清明假期。把它放进任意 GitHub Markdown 文件的 mermaid 代码围栏里就能渲染。

gantt
    title 接口 v2 迁移与小程序 2.0
    dateFormat YYYY-MM-DD
    axisFormat %m-%d
    excludes weekends
    excludes 2026-04-04, 2026-04-05, 2026-04-06

    section 调研
    盘点 v1 接口        :done, audit, 2026-03-02, 5d
    编写 OpenAPI 规范    :done, spec, after audit, 4d
    规范评审            :active, review, after spec, 2d

    section 开发
    鉴权服务重构        :crit, auth, after review, 10d
    资源类接口          :res, after auth, 12d
    客户端 SDK 重新生成  :sdk, after res, 3d

    section 切换
    预发环境泡测        :soak, after sdk, 5d
    公测开放            :milestone, beta, 2026-05-04, 0d
    下线 v1             :dep, after beta, 2w

逐行读一遍:

  • dateFormat YYYY-MM-DD 告诉 Mermaid 怎么读你打进去的日期。它管的是输入格式,不是输出, , 改它不会改变坐标轴。
  • axisFormat %m-%d 才是输出侧,坐标轴显示为"03-02"这样的形式。跨度超过一个季度时用 %V 显示周次更好读。
  • excludes weekends 让所有横条跳过周六和周日,作用于整张图, , 没有针对单个任务的开关。
  • 第二行 excludes 排除了 2026 年清明的三天。但要注意:调休上班的那个周六,Mermaid 没有办法表达。国内的法定节假日通常伴随调休,而这个格式只能减不能加, , 想让某个周六算成工作日,只能改成绝对日期硬写,或者干脆把排期交给真正的工作日历去算。
  • 盘点 v1 接口 :done, audit, 2026-03-02, 5d, , 标签、id、一个绝对开始日(周一)、五天。工期含首日,所以它在 3 月 6 日(周五)结束。
  • after audit 意思是"audit 结束后开始", , 因为排除了周末,它落在 3 月 9 日周一,而不是 7 号周六。
  • :crit, auth, ... 把这条横条涂成关键路径的颜色。注意是"涂", , 原因见下面那一节。
  • 资源类接口 :res, after auth, 12d 完全没有标签,第一个字段只是一个 id。没有标签就表示尚未开始的工作。
  • 公测开放 :milestone, beta, 2026-05-04, 0d 是固定日期上的一个零长度标记。里程碑和别的任务一样可以有 id,所以最后一行的 after beta 是合法的。
  • 2w 是两周。Mermaid 也接受 h 和 m,在这里很少用得上。

section 之间的空行纯属装饰,Mermaid 会忽略,我们的导入器也忽略。但还是留着, , 一个四十行的代码块没有空行,在 diff 里根本没法看。

任务行字段速查

每个字段和修饰符的作用,以及它实际长什么样。

字段或修饰符示例作用
idaudit给任务起的一个名字,好让 after 能引用它。不能有空格和标点。除非有别的任务依赖它,否则可以不写。
afterafter audit在指定任务结束后开始。只有完成-开始,没有延时。可以写多个 id, , after a b 等两者中较晚的那个。
done:done, audit, …把横条画成已完成。没有百分比, , 100% 和"基本做完了"看起来一模一样。
active:active, review, …把横条画成进行中,同样不带任何数字。
crit:crit, auth, …把横条涂成关键色。它是你手打上去的一个断言,不是 Mermaid 推导出来的, , 没有任何东西拿它跟依赖关系核对。
milestone:milestone, beta, …画成菱形而不是横条。和 0d 搭配使用。
工期单位5d · 2w · 8h天、周、小时(还有 m)。含开始当天:周一起算的 5d 在周五结束。
结束日期2026-03-02, 2026-03-06用第二个日期代替工期,适用于结束日被外部固定的情况。
dateFormatdateFormat YYYY-MM-DD文件里的日期按什么格式解析。头部声明,每张图写一次。
axisFormataxisFormat %m-%d坐标轴标签怎么显示,用 strftime 占位符。纯粹是外观。
excludesexcludes weekends非工作日。也接受具体日期(excludes 2026-04-06)和星期名。作用于整张图。

四个一定会咬你的地方

1. 工期包含开始当天。从 5 号周一算起的 5d 到 9 号周五结束,不是 10 号。这里差一天,会把整份文件里所有任务都推移,而且照样渲染得完美无缺。

2. after 碰上 excludes weekends,才是真正出 bug 的地方。如果前置任务在周五结束,后继任务应当从周一开始,而不是周六。任何用"加一个自然日"来解析 after 的工具,都会在一份明令排除周末的文件里悄悄把任务排到周末。(我们的工具一度也是如此。现在有一条测试专门断言:任何推导出的日期都不会落在被排除的日子上。)

3. 没有转义机制。冒号开启字段列表,逗号分隔字段,所以一项名为 Phase 2: design, review 的任务会被解析成完全不同的东西。任务名里别用冒号和逗号。

4. 无法解析的工期会静默变成零。写成 3dd,你得到的是一条零长度的横条,而不是一个报错。批量改完之后,记得扫一遍有没有看不见的任务。

完成 → 开始ABB 等待 A开始 → 开始ABB 等待 A完成 → 完成ABB 等待 A开始 → 完成ABB 等待 A
"after" 是零延时的完成-开始,这也是这个格式唯一有的关系类型。

Mermaid 表达不了的东西

它是一种图示格式,不是排程引擎。你一旦想让图去回答问题、而不只是把一个答案画出来,差别立刻就显出来了:

这些都不说明它是个糟糕的格式,只说明它是一种发布格式:适合把一份进度计划展示出来,不适合把它推算出来。这正是往返转换重要的原因。

所以往返转换会有损耗,但损耗方式是已知且乏味的。导出时,gantts.app 把 100% 映射为 done,中间的任何值映射为 active;导入时把 active 读回为 50%, , 这是一个猜测,工具会明说,而不是让你在某份状态报告里才发现。写不成 after 的依赖关系会退化为绝对日期,这些日期依然正确,只是不再便于维护。

有一处刻意的不对称,而且它不是 bug:crit 会被导出,但从不被导入。往外写的时候它是推导出来的, , 编辑器已经从依赖关系网络算出了关键路径,所以写下去的那个标签当时是真的。往里读的时候,它只是某个人在一份可能已经过期好几周的文件里打下的一个词,相信它就等于允许一张旧图把一条并不关键的链条涂成红色。所以它被写出、然后被无视:你在导入之后看到的关键路径,是重新算过的,不是被声明出来的。

顺带说明我们这边关键路径的口径:它是"按当前位置"计算的, , 一条依赖关系只能把任务往后推,永远不会把它往前拉;工具算的是总浮动时间,不算自由浮动时间。所以一份从 Mermaid 导进来、日期被作者手工排得很松的计划,导入后不会被自动压紧,关键路径反映的是这些横条实际所在的位置。

可视化编辑,再把代码粘回去

能渲染 Mermaid 的工具不少。一直缺的是反方向, , 拖动横条,然后把语法拿回来。

  1. 在 gantts.app 里粘贴或打开你的图, , .mmd 文件,或含有代码围栏的 .md 文件,都可以。它按内容识别 gantt 代码块,而不是看扩展名。
  2. 像编辑任何图表一样拖动、连线、改日期。excludes weekends 会把工作日历打开,因此产出的日期与它来源的那份文件一致。
  3. 点⬇ 导出,选 🧜 Mermaid 甘特图(文本),点复制到剪贴板或下载 .mmd,粘回你的 README,提交这个 diff。
  4. 提交前先勾一下关键路径看一眼:导出的 crit 标签用的就是这一次计算的结果,所以你在图上看到什么,README 里写的就是什么。

对用大模型起草进度计划的人还有一个不错的副作用:让它输出 Mermaid gantt 语法,粘进来,你就得到一张真正可编辑、还带关键路径的图表, , 不需要 API 密钥,也不需要后端。

undefined

常见问题

Mermaid 里怎么写甘特图?

代码块以 gantt 开头,加上 dateFormat YYYY-MM-DD,然后写 section 标题,标题下按"名称 :tag, id, start, duration"的形式写任务行,例如 "Research :done, res, 2026-01-05, 5d"。

Mermaid 里的 5d 包含开始当天吗?

包含。从 5 号周一开始的 5d 任务在 9 号周五结束。这种含首日的计数方式是最常见的差一天错误来源。

Mermaid 甘特图里依赖关系怎么写?

在 start 字段写 "after someId"。它永远是无延时的完成, 开始关系,开始, 开始、完成, 完成以及延时都无法表达。

Mermaid 能显示完成百分比吗?

不能,它只有 done 和 active 两个标签。把 active 读成某个具体百分比只能靠猜;gantts.app 取 50%,并且会明确告知。

Mermaid 甘特图在哪里能渲染?

GitHub、GitLab、Notion 和 Obsidian 都能在 Markdown 里原生渲染,mermaid.live 也可以在浏览器里渲染。

可以把 Mermaid 甘特图变成可编辑的图表吗?

可以。在 gantts.app 里打开 .mmd 或 Markdown 文件,可视化编辑之后用"导出 ▸ Mermaid 甘特图"把更新后的语法复制回去。

相关模板

作者 Uttam Regmi. Synth88 Labs 创始人,在迪拜打造注重隐私的网页与移动应用。 完整简介 · LinkedIn · Medium · GitHub

本文也提供英文版本。

Advertisement

免费创建你的甘特图

在浏览器中直接使用,无需注册。数据保存在你自己的设备上。

打开编辑器