pdg XML → PDF

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.

Try it — edit the source Open in Playground
<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

Spacing

Transparent space outside the border — the one decoration that lives outside the element's own box.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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

Spacing

Space between the border and the content — the room a boxed paragraph breathes in.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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 & border

A solid fill behind the content, covering the border-box and clipped by any rounded corners.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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 & border

Stroked edges around the border-box, plus the corner rounding that shapes them.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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

Effects

A drop shadow cast under the border-box, following its rounded corners.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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

Effects

Fade a whole element — its paint and its entire subtree — as one group, exactly like CSS opacity.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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

Effects

Crop a box's content to its border-box on both axes, following the rounded corners.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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

Size

Fix or bound the box's dimensions; without them the box shrink-wraps its child.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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

Alignment

Place the child inside a box that's larger than it — when a fixed or minimum size leaves slack.

AttributeValuesDefaultDescription
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.

Try it — edit the source or tweak the controls Open in Playground
<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>