Tabs

Tabs turn headings into tab labels. Every direct child heading at the first heading's level starts a tab; deeper headings are content. This is the cleanest degradation in the vocabulary, which is why tabs use headings rather than a separator: a stock renderer shows the headings and their content, in order.

Tab state uses radio inputs, so no JavaScript is involved. active=<n> picks the initially open tab.

Attributes

Attribute Values Default
active A positive integer within the tab count 1

Content must be headings and their blocks. The first heading found sets the tab level; every heading at that level starts a new tab and anything deeper is content inside it. Content before the first heading is an error, as is a heading shallower than the first.

Downgrade: the headings and their content, unchanged. This is the cleanest fallback in the vocabulary, and it is the reason tabs use headings rather than a separator.

Watch for: tab groups do not synchronize. Radio inputs cannot do it without a script, and scripts are out of scope.

Examples

Headings become the tab labels. A renderer with no tab support shows the sections one after another, which is the downgrade.

canonical

Source

:::tabs
### macOS
`brew install markset`

### Windows
`winget install markset`
:::

Rendered

brew install markset

winget install markset

Downgrade

### macOS

`brew install markset`

### Windows

`winget install markset`

active picks which tab opens. Panels switch with radio inputs, so there is no script.

active tab override

Source

:::tabs{active=2}
## A
a
## B
b
:::

Rendered

a

b

Downgrade

## A

a

## B

b

The first heading level found sets the tab level. Anything deeper is content inside that tab.

deeper headings are tab content

Source

:::tabs
## A
### Sub
text
## B
:::

Rendered

Sub

text

Downgrade

## A

### Sub

text

## B

Tab content is ordinary blocks, so constructs nest inside it with the usual fence rule.

nested: a card inside a tab

Source

::::tabs
### A
:::card
x
:::
### B
y
::::

Rendered

x

y

Downgrade

### A

x

### B

y

What the validator catches

Every error below is specified; nothing degrades silently.

empty content

invalid

Source

:::tabs
:::

Rendered

Diagnostics: TABS_NO_HEADINGS

wrong content type: no headings

invalid

Source

:::tabs
just text
:::

Rendered

just text

Diagnostics: TABS_NO_HEADINGS

content before the first heading

invalid

Source

:::tabs
intro
### A
x
:::

Rendered

intro

A

x

Diagnostics: TABS_CONTENT_BEFORE_HEADING

All 15 cases for tabs are in the conformance browser. The normative text is spec §4.