Tabs
把多个视图装进同一块空间——读者点 tab 切换显示什么,节省垂直空间。 适合"同一信息的多种表达"(多语言代码 / raw 数据 vs chart / 桌面 vs 移动端 vs API)。
When to use
- ✅ 多语言代码示例(同一段逻辑用 JS / Python / Rust 三种实现)
- ✅ 同一数据的多种视图(原始 JSON / 表格 / 图表)
- ✅ 多平台/环境对比(macOS / Windows / Linux 安装步骤;iOS / Android 截图)
- ✅ API 的请求 / 响应 对比(curl / Node.js / Python 调用方式)
- ❌ 平级独立内容(不需要切换,全部并列展示)→ 用 Layout grid
- ❌ 严格序列(step 1 → 2 → 3)→ 用 Stepper
- ❌ 强对比(用户必须看见所有项才能决策)→ 用 Layout,tabs 会让其他选项"看不见"
Basic syntax
\```tabs
:::tab title=JavaScript
\```js
console.log('hello');
\```
:::
:::tab title=Python
\```py
print('hello')
\```
:::
:::tab title=Rust
\```rust
println!("hello");
\```
:::
\```
渲染:顶部一排 tab bar,第一个 tab 默认激活;点击其他 tab 切换内容区。tab 之间共用同一垂直空间。
All options
Block-level: ```tabs
| Option | Type | Default | Purpose |
|---|---|---|---|
default |
int / string | 0(第一个) |
默认激活 tab 的 index 或 title |
position |
enum | top |
tab bar 位置(top / bottom) |
Tab-level: :::tab
| Option | Type | Default | Purpose |
|---|---|---|---|
title |
string | (必填) | tab bar 上显示的文字。建议短(< 20 字符) |
disabled |
bool | false |
灰显且不可点击(用于占位 / 预告) |
title含空格请加引号:title="My Tab"。
Examples
Example 1:多语言代码
\```tabs
:::tab title=JavaScript
\```js
async function getUser(id) {
const r = await fetch(`/api/user/${id}`);
return r.json();
}
\```
:::
:::tab title=Python
\```py
import requests
def get_user(id):
return requests.get(f'/api/user/{id}').json()
\```
:::
:::tab title=Go
\```go
func GetUser(id string) (*User, error) {
resp, err := http.Get("/api/user/" + id)
// ...
}
\```
:::
\```
渲染:3 个 tab "JavaScript / Python / Go",点击切换不同语言代码。读者看自己熟悉的那一种就好。
Example 2:富内容(含 callout / 列表)
\```tabs
:::tab title=macOS
1. 下载 `.dmg`
2. 拖到 Applications
3. 启动
> [!INFO]
> Apple Silicon 和 Intel universal 二进制
:::
:::tab title=Windows
1. 下载 `.msi`
2. 双击安装
3. 从开始菜单启动
> [!WARN]
> 需要 Windows 10+
:::
:::tab title=Linux
\```bash
sudo apt install rho # Debian/Ubuntu
sudo dnf install rho # Fedora
\```
或下载 `.AppImage` 直接运行。
:::
\```
渲染:3 平台并列在 tabs 里。Tab 内容可含任意 markdown(列表、代码块、callout、链接),不只是纯文字。
Example 3:同一数据的 3 种视图
\```tabs
:::tab title=Raw
\```json
{"q1": 100, "q2": 130, "q3": 95, "q4": 180}
\```
:::
:::tab title=Table
| Quarter | Revenue |
|---|---|
| Q1 | 100 |
| Q2 | 130 |
| Q3 | 95 |
| Q4 | 180 |
:::
:::tab title=Chart
\```vega-lite
{
"data": {"values": [{"q":"Q1","v":100},{"q":"Q2","v":130},{"q":"Q3","v":95},{"q":"Q4","v":180}]},
"mark": "bar",
"encoding": {"x": {"field": "q"}, "y": {"field": "v", "type": "quantitative"}}
}
\```
:::
\```
渲染:同一组季度营收数据,三种视图(JSON / 表格 / 柱状图)。读者按需切换;表格适合精确读、图表适合趋势看、JSON 适合复制走。
Example 4:指定默认激活 + disabled
\```tabs default="Production"
:::tab title=Development
开发环境配置...
:::
:::tab title=Staging
预发环境配置...
:::
:::tab title=Production
**生产环境配置**(默认显示,因为最关键)
:::
:::tab title=Edge disabled=true
Edge 网关配置 — 🚧 v0.7 推出
:::
\```
渲染:默认显示 "Production" tab(因为 default="Production"),不是第一个。"Edge" tab 灰显且不可点击。
Plain-text fallback behavior
:::tab 是 markdown directive 容器。在不支持 directive 的 reader 里:
:::tab title=JavaScript
content
:::
→ :::tab title=... 和 ::: 显示为字面量;tab 内的 markdown(代码块、列表、链接)正常渲染。所有 tab 内容展开为一连串显示——读者能看到所有信息,只是失去 "选一个看" 的交互。
具体各 reader:
| Reader | 渲染效果 |
|---|---|
| Rho | 完整 tabs(顶部 bar + 切换) |
| GitHub web | :::tab title=... 字面量 + tab 内容并列展开 |
| Obsidian | 同上(除非装了 directive 插件) |
| VS Code 默认预览 | 同上 |
| cat / less | plain text |
所有 tab 内容都可读——这是 plain-text fallback 的核心。读者最坏看到的是"全部 tab 内容堆在一起",不是错误。
Common pitfalls
1. 忘记 title
\```tabs
:::tab ← ❌ 缺 title
内容
:::
\```
→ tab bar 显示空白或 "Tab 1"。title 是必填。
2. title 含空格忘记引号
:::tab title=My Tab ← ❌ "Tab" 被当成下个 modifier
:::tab title="My Tab" ← ✅
3. tab 数过多 (>5)
| tab 数 | 体验 |
|---|---|
| 1-3 | 最佳 |
| 4-5 | OK |
| 6-8 | tab bar 拥挤;移动端会折行或滚动 |
| > 8 | 反模式,改用 Layout grid + cards 全部展开或 sidebar nav |
4. tab 内容深度极不均衡
\```tabs
:::tab title=A
A 方案非常长描述:5 段、3 列表、嵌套 callout、代码块……
:::
:::tab title=B
B 方案一句话。
:::
\```
→ 切到 B 时空荡,切到 A 时撑满。视觉跳变过大。 改进:补 B 内容到对等深度;或改用 Layout grid 同时展示让读者横向比较。
5. 缺 ::: 关闭
\```tabs
:::tab title=A
A 内容
← ❌ 缺 :::
:::tab title=B
B 内容
:::
\```
→ 整个 tabs 块解析失败。每个 :::tab 必须配对 ::: 关闭。
6. 嵌套 tabs(不推荐)
\```tabs
:::tab title=Outer
\```tabs ← ⚠️ tabs 套 tabs,UI 极易混乱
:::tab title=Inner
:::
\```
:::
\```
→ 技术上 Nested DSL 支持,但视觉上读者很难分清外层和内层 tabs 边界。 改进:把内层 tabs 提到外面平级,或改用 stepper(外层 step 内放 tabs)。
7. tabs 里嵌 interact 块——可以,但注意状态
:::tab title=Demo
\```interact
slider x 0 10 5 1
template stl:
[选中] -> [{x}]
\```
:::
✅ 合法。但切到其他 tab 再切回来时,slider 的状态可能 reset 到初始值(看 reader 实现)。重要的 demo 别藏在非默认 tab。
Tabs vs Stepper vs Layout — 选择依据
| 场景 | 用 |
|---|---|
| 多视图 / 多语言 / 多版本(读者选一个看) | Tabs |
| 严格步骤序列(一步步走,含 Prev/Next) | Stepper |
| 平级对比(读者必须看到全部一起) | Layout grid |
| 时间事件(带日期) | Timeline |
See also
- Stepper — 严格序列展示,含 Prev/Next 进度
- Modal — 隐藏内容,按需展开
- Layout grid + cards — 平级对比,同时展示
- Nested DSL — tabs 内嵌 callout / interact 等
- Plain-text fallback principle