html
html
HTML primitives — REAL HTML + CSS as a promo stage, one trial per scene.
Read the rig's notes
`html` is the <ui> twin: a texture stage that takes ordinary markup and a
stylesheet — pug children ARE the DOM (div.hero, h1(text=…), ul/li, table,
input, img(src="image:…")) and a `style(text="…")` child is the CSS. It
renders through the WICG html-in-canvas API (drawElementImage on a
<canvas layoutsubtree>, Chromium behind --enable-features=CanvasDrawElement)
and falls back to an SVG foreignObject snapshot everywhere else — the two
tiers are pixel-identical for the same markup (packages/engine/layers/html/).
`html3d` is the <ui3d> twin: every TOP-LEVEL markup child becomes its own
world plane, placed from its live CSS layout box and animatable with the
same delta tracks a ui3d child takes.
Time is deterministic: the root carries `--t` (scene seconds) and `--p`
(0..1), and every CSS @keyframes animation is pinned to the frame's time
(paused + negative delay), so scrub / capture / export all agree.
Sizing: width/height is the stage in mm like <ui> (bare tag = 1920×1080
wall); `coords_width` lays the DOM out at that many CSS px and scales it
onto the stage — the way to put a 390px phone page on a 71mm glass.
Assets stay NAMED: img(src="image:cards-img2.jpg"), url("font:…").
PIXEL-SPACE SECTION (01–07) — full-frame billboards, camera 960 540 1320.
01. hello — gradient text, flex hero, a --p progress bar
02. typography — paragraphs, lists, drop cap, balance, blockquote, mark
03. grid — a CSS-grid dashboard: auto-fit tiles, grid areas, shadows
04. keyframes — @keyframes choreography seeked deterministically
05. table — a pricing <table>, <code>, <kbd>, <abbr>
06. code — <pre><code> with span highlighting + counter line numbers
07. forms — native <input>/<select>/<progress>/<meter>/<button>
WORLD-SPACE SECTION (08–10) — mm, lit like a product shot.
08. device — iphone + laptop, each screen an html stage (coords_width)
09. panels — three glass <html> panes (no fill) yawed over spheres
10. exploded — html3d: a dashboard's children separate into Z layers
Capture: `nx run tools:capture:browser -- --project promos/primitives/html/html.promo`
(the webgl-node capture has no DOM — html stages render empty there).
Preview: /packages/runtime/index.html?project=promos/primitives/html/html.promo- Topic
- uis
- Scenes
- 10
- Kind
- reference rig
//
HTML primitives — REAL HTML + CSS as a promo stage, one trial per scene.
`html` is the <ui> twin: a texture stage that takes ordinary markup and a
stylesheet — pug children ARE the DOM (div.hero, h1(text=…), ul/li, table,
input, img(src="image:…")) and a `style(text="…")` child is the CSS. It
renders through the WICG html-in-canvas API (drawElementImage on a
<canvas layoutsubtree>, Chromium behind --enable-features=CanvasDrawElement)
and falls back to an SVG foreignObject snapshot everywhere else — the two
tiers are pixel-identical for the same markup (packages/engine/layers/html/).
`html3d` is the <ui3d> twin: every TOP-LEVEL markup child becomes its own
world plane, placed from its live CSS layout box and animatable with the
same delta tracks a ui3d child takes.
Time is deterministic: the root carries `--t` (scene seconds) and `--p`
(0..1), and every CSS @keyframes animation is pinned to the frame's time
(paused + negative delay), so scrub / capture / export all agree.
Sizing: width/height is the stage in mm like <ui> (bare tag = 1920×1080
wall); `coords_width` lays the DOM out at that many CSS px and scales it
onto the stage — the way to put a 390px phone page on a 71mm glass.
Assets stay NAMED: img(src="image:cards-img2.jpg"), url("font:…").
PIXEL-SPACE SECTION (01–07) — full-frame billboards, camera 960 540 1320.
01. hello — gradient text, flex hero, a --p progress bar
02. typography — paragraphs, lists, drop cap, balance, blockquote, mark
03. grid — a CSS-grid dashboard: auto-fit tiles, grid areas, shadows
04. keyframes — @keyframes choreography seeked deterministically
05. table — a pricing <table>, <code>, <kbd>, <abbr>
06. code — <pre><code> with span highlighting + counter line numbers
07. forms — native <input>/<select>/<progress>/<meter>/<button>
WORLD-SPACE SECTION (08–10) — mm, lit like a product shot.
08. device — iphone + laptop, each screen an html stage (coords_width)
09. panels — three glass <html> panes (no fill) yawed over spheres
10. exploded — html3d: a dashboard's children separate into Z layers
Capture: `nx run tools:capture:browser -- --project promos/primitives/html/html.promo`
(the webgl-node capture has no DOM — html stages render empty there).
Preview: /packages/runtime/index.html?project=promos/primitives/html/html.promo
promo#html
// =======================================================================
// SCENE 01 · HELLO — a flex hero, gradient text, --p drives the bar
// =======================================================================
scene#s01-hello(duration=6 transition=match-move transition-duration=0.8)
camera(type=perspective fov=48 near=0.1 far=8000 position="960 540 1320" look_at="960 540 0")
position
0 960 540 1360
6 easeInOutCubic 960 540 1300
background(top=#081120 bottom=#04060c)
postprocessing
step(name=render)
step(name=unreal_bloom strength=0.18 radius=0.4 threshold=0.85)
haze#s01-haze-a(match=haze-a position="1320 760 -650" opacity=0.17 color=#0f6fd6 size="3100 2360" pulse=0 decay=0)
position
0 0 0 0
6 easeInOutCubic -80 40 0
haze#s01-haze-b(match=haze-b position="420 300 -680" opacity=0.11 color=#5e2a9d size="2500 1960" pulse=0 decay=0)
position
0 0 0 0
6 easeInOutCubic 80 -40 0
haze#s01-dot-a(match=dot-a position="180 880 120" opacity=0.5 color=#9be9ff size="76 76" pulse=0 decay=0)
haze#s01-dot-b(match=dot-b position="1780 620 60" opacity=0.42 color=#e7fbff size="52 52" pulse=0 decay=0)
text#s01-label(text="01 · hello — real DOM on a WebGL plane" kind=layer size=110 worldHeight=34 color=#8ea3c8 weight=600 align=center position="960 1032 150")
html#s01-page(width=1920 height=1080 x=960 y=540)
opacity
0 0
0.7 easeOutCubic 1
style