Skip to main content

Lists

A <x:list> is a vertical stack of <x:li> items, each flowed and wrapped like a mini <x:textbox> but with a hanging indent: the marker sits in the gutter and continuation lines align to the text column, not back under the marker. It is the ordered/unordered list SVG never got, and lowers to a <g> of drawn bullet shapes plus one plain <text> of positioned <tspan>s — live and selectable.

Compiling…
Bullet and numbered listsOpen in viewer ↗Edit in Playground →
Bullets that cycle by depth, decimal→alpha→roman numbering with a resuming outer counter, and a list flowed inside a referenced card.

Syntax

<x:list x="40" y="80" width="300" list="bullet" font-size="14" item-spacing="5">
<x:li>Top-level item that wraps under its own text column</x:li>
<x:li indent="1">A nested item — one indent step in</x:li>
<x:li indent="2">Deeper still</x:li>
</x:list>

Hanging indent and nesting

Each <x:li> is one item; indent="N" sets its nesting level (0 is the top). Every level steps the text column right by the indent step, and continuation lines of a wrapped item align to that column — the marker hangs in the gutter to its left. An empty item still advances one line.

Markers cycle by depth

Bullet markers are drawn shapes, not font glyphs, so they don't vary by font and stay optically balanced. They cycle every three levels: a filled disc, a hollow ring, then a filled square. The shapes are area-compensated — the square's side is r·√π so its area matches the disc's, and the ring's outer diameter is enlarged about 12% since a hollow mark reads lighter.

With list="number", markers cycle decimal → lower-alpha → lower-roman by depth and keep an outline counter per level. The counter restarts whenever nesting pops back to a shallower level, so a top item after a sublist resumes where it left off — 1. 2. a. b. 3. Numbers are right-aligned into the gutter, so 1. and 10. share a column edge.

list="none" suppresses the marker but keeps the indent. A marker on the list — or on a single <x:li> — forces a named drawn shape (disc / circle / square / dash) or any literal string (, , , …), overriding the cycle.

Flowing inside a shape

Instead of x / y / width, give the list in="#rect" to take its left edge, top, and width from a referenced shape's bounding box (a baked reference). That box also supplies the height for valign, so a list can sit top, middle, or bottom inside a card.

Attributes

AttributeValuesDefaultDescription
listbullet / number / nonebulletMarker style for the whole list.
markerdisc / circle / square / dash, or a literal stringForce a marker (drawn shape or literal text); overrides the list cycle.
marker-sizenumber1Scale factor on the drawn bullet shapes.
marker-fillcolorfillMarker color (shapes and number/character markers).
x y widthlengthThe block's left edge, top, and content width.
in#idBind geometry to a referenced shape's bounding box; also supplies the height for valign.
valigntop / middle / bottomtopVertical placement within the height.
indentlength1.5emPer-level indent step.
marker-gaplength0.5emGap between the marker and the text column.
item-spacinglength0.35emExtra vertical gap between items.
font-*, line-height, fillas textBase style for every item.

An <x:li> may set indent="N", marker="…", and font-size="…" (a smaller sub-point). It inherits the list's size and line-height otherwise, and its marker scales to match its size.

How it lowers

A <x:list> compiles to a <g> containing the drawn bullet shapes plus one plain <text> whose positioned <tspan>s carry the item text and any number/character markers — no runtime, fully selectable.

v0 limits

One style per item beyond font-size (inline <tspan> fill/weight inside an item is not yet applied). No shrink-to-fit or height clipping — the list flows from valign within the height but doesn't shrink to fit it. Number, roman, and character markers are live text (the glyphs must exist in the font); bullet shapes are drawn and font-independent.

See also