Reference
Styles
A box model that rides on any tag via style: attributes — margin and padding, fills and borders, shadows, sizing, alignment. margin becomes outer space; everything else decorates the element's own box, transparently, whatever the element.
Styles — style:*
The box model. Any element can carry style:* attributes — spacing, sizing, fills, borders, shadows, alignment — applied transparently, whatever the element.
margin becomes outer space; everything else decorates the element's box —
transparently, no matter the element. The model is the familiar one, outside in:
margin → border → padding → content, with background filling the
border-box and border-radius rounding it.
Each property has its own page below, with a live example you can edit and, where
it helps, controls to drag. Lengths are px (= pt), pt, or mm (a bare number
is points); colors are hex (#rgb, #rgba, #rrggbb, #rrggbbaa) or a CSS
name.
<vertical style:background="#1b1a17" style:padding="18px"
style:border-radius="12px" style:box-shadow="0 6px 20px #00000033"
style:max-width="240px">
<text color="#ffffff" size="20" bold="true">A styled card</text>
<text color="#b8b2a4" size="12">Padding, radius, and a soft shadow.</text>
</vertical>style:margin
SpacingTransparent space outside the border — the one decoration that lives outside the element's own box.
| Attribute | Values | Default | Description |
|---|---|---|---|
margin |
1–4 lengths | 0 | All sides, CSS order: all · v h · t h b · t r b l. |
margin-top |
length | — | Top side; overrides the shorthand. |
margin-right |
length | — | Right side. |
margin-bottom |
length | — | Bottom side. |
margin-left |
length | — | Left side. |
Margin pushes the element away from its siblings and its container; nothing
paints there — no background, no border. It is the only style: decoration that
doesn't live in the element's box: the parser lifts it into an outer wrapper,
so the box's own paint stays inside the margin, exactly like CSS.
Because margin is that outer space, it collapses a partial fit to "doesn't fit" — a block that only partly fits a page moves whole to the next page rather than splitting through its margin.
<vertical style:background="#efeae0" style:padding="6px">
<rect width="130px" height="20px" fill="#c9c4b4"/>
<rect width="130px" height="20px" fill="#c4341f" style:margin="16px"/>
<rect width="130px" height="20px" fill="#c9c4b4"/>
</vertical>style:padding
SpacingSpace between the border and the content — the room a boxed paragraph breathes in.
| Attribute | Values | Default | Description |
|---|---|---|---|
padding |
1–4 lengths | 0 | All sides, CSS order: all · v h · t h b · t r b l. |
padding-top |
length | — | Top side; overrides the shorthand. |
padding-right |
length | — | Right side. |
padding-bottom |
length | — | Bottom side. |
padding-left |
length | — | Left side. |
Unlike margin, padding is inside the box: the background
fills it and the border surrounds it. It reduces the room handed to the child,
then the box re-expands around the child's measured size.
The padded region is indivisible — a child that only partly fits the page yields "doesn't fit" rather than splitting a padding edge across a page break.
<text style:padding="16px" style:background="#eef2ff"
style:border="1px" style:border-color="#6366f1"
style:border-radius="6px">
Padding holds the text off the border on every side, so the frame never
crowds the words.
</text>style:background
Fill & borderA solid fill behind the content, covering the border-box and clipped by any rounded corners.
| Attribute | Values | Default | Description |
|---|---|---|---|
background |
color | — | Fill color of the border-box. Alpha welcome (#rrggbbaa). |
The fill covers the area inside the margin, under the border and padding; rounded corners clip it, and margin stays transparent around it.
Reach for an alpha color to tint content beneath — #0000001a is black at ~10%
to dim a layer in a <stack>. That beats opacity when you
want a translucent fill behind opaque text, since opacity would never touch the
text but an alpha background reads more clearly as intent.
<horizontal gap="10px">
<text style:padding="10px" style:background="#dcfce7">solid</text>
<text style:padding="10px" style:background="#16a34a55">alpha 55</text>
</horizontal>style:border
Fill & borderStroked edges around the border-box, plus the corner rounding that shapes them.
| Attribute | Values | Default | Description |
|---|---|---|---|
border |
1–4 lengths | 0 | Side widths, CSS order. Per-side: border-top/right/bottom/left. |
border-color |
color | black | Stroke color for every side (one color, all sides). |
border-radius |
length | 0 | Radius for all corners. Per-corner: border-top-left-radius, … |
The border sits between margin and padding;
with padding it insets the content. Per-side widths draw a single rule —
style:border-bottom="1px" is an underline that reserves its own space, unlike
a free-standing <line>. Each corner radius is clamped so it never exceeds half
the box's shorter side, and the same radii round the fill and the
clip region.
Like padding, a border makes the box indivisible across pages: a partial fit becomes "doesn't fit" rather than splitting a border edge between pages.
<vertical gap="12px">
<text style:padding="12px" style:border="2px" style:border-color="#0ea5e9"
style:border-radius="10px">rounded, all sides</text>
<text style:padding="8px 0" style:border-bottom="1px"
style:border-color="#9ca3af">underlined heading</text>
</vertical>style:box-shadow
EffectsA drop shadow cast under the border-box, following its rounded corners.
| Attribute | Values | Default | Description |
|---|---|---|---|
box-shadow |
dx dy blur spread #color | — | Shorthand; each part optional. Omitting blur means a sharp shadow. |
shadow-x |
length | 0 | Horizontal offset; overrides the shorthand. |
shadow-y |
length | 2 | Vertical offset. |
shadow-blur |
length | 4 | Blur radius. |
shadow-spread |
length | 0 | How far the shadow grows beyond the box. |
shadow-color |
color | #0000004d | Shadow color (black at 30% by default). |
Set a shadow with the CSS-like shorthand or the individual shadow-* keys; the
two compose, with the keys overriding parts of the shorthand. Asking for a
shadow at all starts from a soft, neutral default (0 2 4, black at 30%) and
applies your overrides on top.
One subtlety lives in the shorthand: an explicit box-shadow that omits the
blur token means a sharp shadow — style:box-shadow="2 2" gives blur = 0,
not the default. Spell out the blur ("2 2 4") to keep softness. The shadow is
part of the box's own paint, so opacity fades it too.
<text style:padding="14px" style:background="#ffffff" style:border-radius="8px"
style:shadow-y="4px" style:shadow-blur="12px" style:shadow-color="#00000033">
A soft drop shadow under a white card.
</text>style:opacity
EffectsFade a whole element — its paint and its entire subtree — as one group, exactly like CSS opacity.
| Attribute | Values | Default | Description |
|---|---|---|---|
opacity |
0–1 | 1 | Composites the element and everything inside it as one transparency group at this alpha. |
opacity fades the element and everything inside it as a single unit. The
box is rendered at full strength first — background, border, shadow, text,
images, nested boxes, all of it — and then that finished picture is composited
onto the page at the given alpha. This is exactly how opacity works in a
browser, and it has two consequences worth knowing.
Drag the control below. The heading, the body copy, and the two overlapping chips all fade together — a child can't opt out of its parent's opacity:
1 · The whole subtree inherits it. Setting opacity on a box dims its
children too — there is no way for an inner element to stay solid while its
parent is faded. To fade only the background and keep text crisp, don't use
opacity; give the background an alpha color instead
(#1e293b80), which tints only that fill.
2 · Overlaps don't double-darken. Because the group is flattened before
the alpha is applied, two overlapping shapes inside one faded box show a single
flat color where they cross — not a darker band. The two chips above overlap by
30 points and stay one even blue. Put the same opacity on each chip
individually instead and the overlap would composite twice and darken.
Opacity composes with clip: the clip crops the content while the
opacity fades the result, so a faded, rounded, cropped card is one box. The fade
covers the box's own shadow as well, just like the browser.
<box style:opacity="0.5" style:background="#1e293b"
style:padding="14px" style:border-radius="10px">
<vertical gap="10px">
<text color="#ffffff" bold="true" size="15">Quarterly report</text>
<text color="#94a3b8">Heading, body, and the chips below all inherit the
box's opacity.</text>
<stack>
<rect width="90px" height="26px" fill="#38bdf8" style:border-radius="13px"/>
<rect width="90px" height="26px" fill="#38bdf8" style:border-radius="13px"
style:margin="0 0 0 60px"/>
</stack>
</vertical>
</box>style:clip
EffectsCrop a box's content to its border-box on both axes, following the rounded corners.
| Attribute | Values | Default | Description |
|---|---|---|---|
clip |
true | false | false | Truthy: true · 1 · yes · on · hidden · clip. |
A box bounded smaller than its content — by a fixed width/height,
a max-width/max-height, or a stretching parent — can hold more than fits.
clip decides how that overflow is treated, on both axes (like CSS
overflow: hidden). Toggle it on the card below:
With clip on, the child lays out at its full natural size — wider and
taller than the box if it wants — and the box then crops the result to its
content area (inside border and padding) on both axes: a horizontally-overflowing
child is cut at the right edge, a vertically-overflowing one at the bottom,
through the rounded corners, and through the middle of a line if that's where
the edge falls. This is the masking tool: fixed-size thumbnails, teasers, banners.
With clip off, nothing is cut precisely. A vertically-overflowing child
keeps the whole lines that fit and drops the rest; a child that can't be made to
fit the box at all (no room to shrink) is dropped rather than cropped. The bottom
is ragged at a line boundary rather than a clean edge, and content isn't trimmed
to the rounded corners.
Clip pairs naturally with border-radius: it reuses the same
clamped corner radii (shrunk by the padding inset), so an image rounds to the
card's corners. It composes with opacity too — content is
cropped first, then the cropped result fades as one group. Clip is about
overflow, not pagination: it does not make a box splittable across pages.
<vertical style:width="190px" style:height="92px" style:clip="true"
style:background="#0f172a" style:border-radius="12px" style:padding="14px">
<text color="#ffffff" bold="true" size="13">Field notes</text>
<text color="#9fb3c8" size="11">A clipped box crops its content to the
rounded edge, so a long passage shows only its first lines and fades out
cleanly — a teaser, a masked thumbnail, a cropped banner. The rest is cut
exactly at the border, mid-line if need be.</text>
</vertical>style:width / height
SizeFix or bound the box's dimensions; without them the box shrink-wraps its child.
| Attribute | Values | Default | Description |
|---|---|---|---|
width |
length | — | Fixed border-box width (includes border + padding). |
height |
length | — | Fixed border-box height. |
min-width |
length | — | Lower bound on width (the box grows to fill it). |
min-height |
length | — | Lower bound on height. |
max-width |
length | — | Upper bound on width. |
max-height |
length | — | Upper bound on height. |
All dimensions are border-box — they include the border and padding, not just
the content. For each axis the box decides whether it is pinned: a width or
height, or a parent that stretches it (cross="stretch"), pins the axis and
the child fills it; otherwise the box shrink-wraps the child. The final size is
then clamped by min-*/max-* and bounded by the space the parent offered. Any
slack the clamp leaves is distributed by alignment.
A box pinned to a fixed height does not split — too-tall content is clipped
with a warning (add clip to crop it on purpose). A box left to
shrink-wrap, or held open only by min-height, still fragments across pages like
any other block. min-height is the usual way to give cards in a row a uniform
height.
<horizontal gap="10px" cross="stretch">
<text style:padding="10px" style:background="#e0e7ff"
style:min-height="70px" style:max-width="120px">
Bounded width, minimum height — text wraps within 120px.
</text>
<text style:padding="10px" style:background="#fae8ff"
style:width="96px" style:height="70px"
style:align="center" style:valign="center">fixed 96×70</text>
</horizontal>style:align / valign
AlignmentPlace the child inside a box that's larger than it — when a fixed or minimum size leaves slack.
| Attribute | Values | Default | Description |
|---|---|---|---|
align |
left | center | right | left | Horizontal placement within the slack. start/center/end also work. |
valign |
top | middle | bottom | top | Vertical placement within the slack. start/center/end also work. |
Alignment only bites when there's extra room — a fixed or minimum
size, or a stretching parent, left slack around the content. With
no slack the child fills the box and these do nothing. center and middle both
mean centered; right/bottom are the far edges, equivalent to end.
This positions the child within its own box. To distribute several children
along a row or column, use the main/cross alignment of <horizontal> /
<vertical> instead — that's container layout, not the box model.
<horizontal gap="8px">
<text style:width="78px" style:height="58px" style:background="#fee2e2"
style:align="start" style:valign="start">top-left</text>
<text style:width="78px" style:height="58px" style:background="#dbeafe"
style:align="center" style:valign="center">center</text>
<text style:width="78px" style:height="58px" style:background="#dcfce7"
style:align="end" style:valign="bottom">bot-right</text>
</horizontal>