HTML layers in doc.json
The html overlay clip: its fields, the rules the page enforces, and a live layer worked through.
The html overlay clip: its fields, the rules the page enforces, and a live layer worked through.
An HTML layer is an overlay clip of kind html. Its source travels in the
document, so it is sharp on the cloud, in the studio and in every export,
never re-hosted and never counted as an upload.
{
"id": "callout",
"kind": "html",
"start": 2,
"duration": 4,
"html": "<div class=\"c\">Open Code</div>",
"css": ".c{font-family:'Inter';background:#0b0b0d;color:#fff;padding:20px;border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.45)}",
"box": { "width": 452, "height": 132 },
"transform": { "x": 0.7, "y": 0.5, "scale": 1, "rotation": 0 }
}box is the design box in 1080p pixels (the frame is 1920 wide).width, when set, is a fraction of the frame width; absent, the design
size is used.bleed is the room around the box for what paints outside it, a shadow
or a glow. It is derived from the shadows in the CSS when absent.fonts lists a face outside the hosted catalog: an https URL, or a
.woff2 beside the document, which vos push uploads (0.64+). A hosted
family needs no entry: name it in the CSS.anim and motion work as on every layer.live: true re-rasterizes the layer per frame; data holds the values
{{data.name}} fills. See Live layers.A callout is unmistakably the video's and still the product's when it
shares the product's hue and type and contrasts in value, elevation, scale
and place. Three shapes carry that, so a viewer learns them once: a note (a
kicker, a title and a line), a tag (one label on the accent) and a code
block (the payload). vos callout composes them from the product's own
register:
vos brand https://tweakcn.com --out take/BRAND.md
vos callout take note --step copy-click --kicker "index.css" \
--title "Every token you tuned, as CSS variables." --mark ring --leaderThe register is BRAND.md beside the take (bgA is the ground, accent,
fontBody) or --ground #hex --accent #hex --font "…" --body-px 14. The
card inverts the app's value in the product's hue (a light app gets a dark
card, a dark app a light one), keeps the accent for the kicker, sets its
title at 1.35 times the app's body as the camera shows it at the layer's
start, lifts on a real shadow and a hairline, rises in and fades out. Its
window opens a beat after the step's press and closes before the next
scroll or navigation, and it is pinned to the step. --at <s> --seconds <n>
places one without a step; --print prints the clip instead of writing
it.
vos validate take --picture renders the footage under every html layer at
its start and reports the colour difference between the card's ground and
what it covers: a card within a small difference of the app reads as one
more panel, and the validator says so. An unpinned layer whose window holds
a step with an element gets the pin named in a warning.
A callout has a referent. Name it and the layer stays with it:
{
"id": "callout",
"kind": "html",
"start": 2,
"duration": 4,
"html": "<div class=\"c\">Copies the theme as CSS variables</div>",
"css": ".c{font-family:'Inter';background:#0b0b0d;color:#fff;padding:20px;border-radius:16px}",
"box": { "width": 452, "height": 96 },
"transform": { "x": 0.7, "y": 0.5, "scale": 1, "rotation": 0 },
"pin": { "step": "copy", "mark": "ring", "leader": true }
}pin names the referent by one of three things: step, a recorder step's
id from actions.json (hover, click, type and drag steps carry the
element's rect); press, a source second, for a human recording that has
no script (the nearest press names its element); or rect, fractions of
the video frame. The layer is placed a gap off one side of the referent
(side is auto, the first of right, left, below and above with room
inside the frame through the layer's life, or a side by name; gap is
design pixels) and carried with the referent as the camera zooms and pans.
The layer keeps its screen size; only its place follows. mark draws a
ring around the referent or an underline beneath it for the layer's
life, leader a hairline from the layer to the referent, color their
ink. transform stays the fallback for a pin that cannot resolve, and
vos validate says why: an unknown step, a step that touched nothing, a
scroll inside the layer's window, a frame with no room beside the referent.
In the studio a pinned layer says what it is pinned to in its Layout group;
dragging it, or pressing Unpin, gives its place back to the fields.
<br /> closes itself, & is written
out, attribute values are quoted. Malformed markup decodes to nothing, so
vos validate refuses it in words before it ships.assets.vos.so (the platform's own catalogs) is inlined the way the
faces are; an image at any other address paints blank, a file of your
own on vos.so included, so inline it as a data: URI. The validator
names the host.shadow, radius, border, frame and key are
refused on an html clip.animation runs on the wall clock, and the validator
warns; make the layer live instead.motion, never its text with CSS. Text a keyframe
drifts or scales slowly steps a whole pixel at a time, because the browser
places text on whole pixels each time it draws the layer; a layer with
motion is drawn from one raster per picture and glides.{
"id": "progress",
"kind": "html",
"start": 2,
"duration": 4,
"live": true,
"data": { "label": "Rendering" },
"html": "<div class=\"w\"><span>{{data.label}}</span><span>{{t}} s</span><div class=\"bar\"><i></i></div></div>",
"css": ".bar{height:10px;background:#222}.bar i{display:block;height:100%;width:0;background:#4ade80;animation:fill 4s linear forwards}@keyframes fill{from{width:0}to{width:100%}}",
"box": { "width": 520, "height": 110 },
"transform": { "x": 0.5, "y": 0.5, "scale": 1, "rotation": 0 }
}{{t}} is the raw number of seconds, rounded to three decimals, with
trailing zeros dropped: it reads 2, then 2.6, then 2.633, and a bare
1 on every whole second. For a readout that holds its shape, build the
digits from --vos-t, which the page writes on a live layer, and give it
font-variant-numeric: tabular-nums:
.n::after{
counter-reset:
o round(down, var(--vos-t, 0), 1)
d calc(round(down, calc(var(--vos-t, 0) * 10), 1)
- round(down, var(--vos-t, 0), 1) * 10);
content: counter(o) '.' counter(d) ' s';
}Keep the , 0 fallback, or the declaration is invalid wherever the layer is
not live.
vos validate runs the layer's gate and says in words what would not paint.
To look at one moment: vos frames take --at 3.