Skip to Content
Basic markupAdvanced table markup

Advanced table markup

Everything on this page builds on the basic pipe syntax. The short version of the grammar: attributes go before a single |, content after it — on cells, rows, the caption, and the table itself.

Spanning rows and columns

colspan and rowspan work exactly as in HTML:

{| ! Name !! colspan="2" | Contact |- | rowspan="2" | Ada | email || [email protected] |- | phone || 555-0100 |}

Attributes — where they go

OnWritten asUseful attributes
the table{| style="…"style, class, border, width
a row|- style="…"style, class, align, valign, bgcolor
a cell| style="…" | contentstyle, class, colspan, rowspan, scope, align, valign, width, bgcolor
the caption|+ style="…" | textsame global set
{| style="width: 100%" |+ style="caption-side: bottom" | Figures are estimates |- style="background: #f6efe3" ! Region !! style="width: 8em" | Total |- | style="text-align: right" | East || 1,204 |}

Attributes are sanitized: only the allowlisted names survive, and style values are filtered (no expression(), javascript:, imports, or other tricks). Anything not allowed is silently dropped, never rendered.

Pipes inside cells

The attribute separator is a raw |, which collides with wikitext that uses pipes. The rules:

  • A cell that starts with [[ treats every pipe as content — so | [[Page|label]] just works, no escaping needed.
  • Anywhere else, put pipe-bearing markup after an explicit attribute block, or use {{!}}-free alternatives: wrap the cell content so the first pipe you write is the attribute separator: | style="…" | [[Page|label]] and {{Include|param}}.
  • Templates are expanded before table parsing, so a | produced by an include does not break the table.

Nested and indented tables

Open another {| on its own line inside a cell to nest; close each table with its own |}:

{| | outer cell | {| | inner || table |} |}

Prefix the {| line with : characters to indent the whole table — each colon is one level.

Forgiving parsing

The parser repairs sloppy tables instead of failing:

  • You can skip the first |- — the first cell line opens a row for you.
  • Unclosed rows and cells are closed automatically at |- and |}.
  • A table with no cells at all still renders (as one empty cell), so a half-written table never swallows the rest of the page.

How wikitable-card really works

The responsive helpers are pure CSS with one exception: on a wikitable-card table the parser records the plain text of your ! header cells, column by column, and stamps every td with a data-label attribute. The phone view hides the header row and prints each cell as a “Header: value” pair from those labels.

Practical consequences:

  • Card tables need a proper header row (! cells) — no headers, no labels.
  • Labels are per-column position: a colspan in the header row will shift the labels of the columns after it.
  • Header markup is stripped to plain text for the label ('''Bold''' becomes Bold).

For genuinely huge tables, prefer wikitable-scroll (+ wikitable-pinfirst if the first column is the key) over shrinking fonts — horizontal scroll preserves readability; 9px text does not.

HonoWiki (Wiki engine) guide · Content CC BY-SA 4.0