VizForDocs
The language

Placement and layout

Flowing versus absolute, what anchor and bleed are for, why paint order is document order, and when to reach for a group instead of a stack.

A Block flows until you give it a coordinate

Every drawing Block flows inside its parent by default and becomes absolutely positioned as soon as x or y is set. There is no position parameter to switch between the two: supplying a coordinate is the switch.

<vf-text role="title" x="50%" y="30%" anchor="center">Positioned</vf-text>

Coordinates are relative to the nearest enclosing <vf-group>, or to the canvas when there is none — and a percentage resolves against that same frame, not always against the canvas.

anchor decides which point of the Block the coordinates name. The default, top-left, is what CSS does; center is usually what you want for a centred element, because it removes the need to subtract half the element's own size.

bleed is how a Block declares that running past the safe area is deliberate — a full-width band, a glow spilling off a corner. Nothing then remarks on it. Say it on purpose: the safe area is the region the destination keeps clear of its own chrome and its own crop, so an element that reaches the edge by accident is the one a platform cuts through, and this is how you say yours does not. Reaching past it is an observation, never a failure.

Paint order is document order

Later siblings draw on top of earlier ones. There is no z-index, and there is no parameter that would let one exist. To move something in front of something else, move it in the document — block.reorder is the command for that.

Groups and stacks are different tools

<vf-stack> distributes children along an axis. Its parameters are CSS flexbox with the names shortened: direction rather than flex-direction, justify taking between rather than space-between, align taking start rather than flex-start. gap and padding are bare numbers in px — not CSS lengths, and never a CSS shorthand.

<vf-group> assembles several Blocks into one thing that moves, rotates, scales and clips as a unit. It can carry a fill, a radius, a shadow and a blur of its own, so a card is a group rather than a shape with things balanced on top of it.

Grouping never moves the picture. block.group rebases its children into the new group's coordinate space, so what was on screen stays where it was. When it cannot do that arithmetic — a child sized as a percentage, or with no declared size — it refuses and names the frame parameter rather than silently resolving a percentage into today's pixels.

Lengths, colours and numbers

  • Lengths are 120, 120px or 38% — a single value, never a CSS shorthand like 10px 20px.
  • Colours are #rgb or #rrggbb. No rgb(), no colour names, no alpha — the one exception is a gradient stop, where #000000@0.6 carries an opacity and @0 is fully transparent, which is how a scrim over a photograph fades out instead of ending on a visible edge.
  • Numbers are bare: gap="24", not gap="24px".

Every parameter is written as an HTML attribute, so on the wire every value is a string. The Block reference prints the value space each one actually accepts — a colour, a length, an integer, an asset:// URI — beside its name.

Making an edge, a lift and a glow

Three appearance parameters get reached for wrongly often enough to be worth naming here:

  • A glow is fade on a shape, not a lowered opacity. A translucent disc still has a visible edge, and the edge is what reads as a mistake.
  • A lift off the surface behind is shadow on a shape or a group. fade cannot do it for a rectangle.
  • A frosted panel is backdrop-blur, which softens what is behind the Block and leaves the Block sharp — and it needs a translucent fill in front of it, or the panel simply covers what it blurred. blur is the other one: it softens the Block itself, edges included, which is depth of field.

On this page