f327833374
# Conflicts: # docs/docs.json # docs/guides/feedback.mdx # docs/weekly-updates.mdx
271 lines
12 KiB
Plaintext
271 lines
12 KiB
Plaintext
---
|
||
title: HTML Schema Reference
|
||
description: "Complete reference for authoring HyperFrames HTML compositions."
|
||
---
|
||
|
||
This is the full schema reference for HyperFrames compositions. For a gentler introduction, see [Compositions](/concepts/compositions) and [Data Attributes](/concepts/data-attributes).
|
||
|
||
## Overview
|
||
|
||
HyperFrames uses HTML as the source of truth for describing a video:
|
||
|
||
- **HTML clips** = video, image, audio, composition
|
||
- **[Data attributes](/concepts/data-attributes)** = timing, metadata, styling
|
||
- **CSS** = positioning and appearance
|
||
- **GSAP timeline** = animations and playback sync (see [GSAP Animation](/guides/gsap-animation))
|
||
|
||
## Framework-Managed Behavior
|
||
|
||
The framework reads data attributes and automatically manages:
|
||
|
||
- **Primitive clip timeline entries** — reads `data-start`, `data-duration`, and `data-track-index` from clips and adds them to the GSAP timeline
|
||
- **Media playback** (play, pause, seek) for `<video>` and `<audio>`
|
||
- **Clip lifecycle** — clips are mounted/unmounted based on `data-start` and `data-duration`
|
||
- **Timeline synchronization** — keeps media in sync with the GSAP master timeline
|
||
- **Media loading** — waits for all media to load before resolving timing
|
||
|
||
Mounting/unmounting controls **presence**, not appearance. Transitions (fade in, slide in) are animated in scripts.
|
||
|
||
<Warning>
|
||
Do not manually call `video.play()`, `video.pause()`, set `audio.currentTime`, or mount/unmount clips in scripts. The framework owns media playback and clip lifecycle. See [Troubleshooting](/guides/troubleshooting) for more details.
|
||
</Warning>
|
||
|
||
## Viewport
|
||
|
||
Every composition must include `data-width` and `data-height` on the root element:
|
||
|
||
```html
|
||
<div id="main" data-composition-id="my-video"
|
||
data-start="0" data-width="1920" data-height="1080">
|
||
<!-- clips -->
|
||
</div>
|
||
```
|
||
|
||
Common sizes:
|
||
- **Landscape**: `data-width="1920" data-height="1080"`
|
||
- **Portrait**: `data-width="1080" data-height="1920"`
|
||
|
||
## All Clip Attributes
|
||
|
||
| Attribute | Applies To | Required | Description |
|
||
|-----------|-----------|----------|-------------|
|
||
| `id` | All | Yes | Unique identifier (e.g., `"el-1"`). Used for relative timing references and CSS targeting. |
|
||
| `class="clip"` | Visible elements | Yes | Enables runtime visibility management. Omit for audio-only clips. |
|
||
| `data-start` | All | Yes | Start time in seconds (e.g., `"0"`, `"5.5"`), or a clip ID reference for [relative timing](#relative-timing) (e.g., `"intro"`). |
|
||
| `data-duration` | video, img, audio, nested composition hosts | See below | Timeline slot duration in seconds. **Required** for images and nested composition hosts. Optional for video/audio (defaults to source duration). |
|
||
| `data-track-index` | All | Yes | Timeline track number. Controls z-ordering (higher = in front). Clips on the same track cannot overlap. |
|
||
| `data-media-start` | video, audio | No | Playback offset / trim point in source file (seconds). Default: `0`. See [Data Attributes](/concepts/data-attributes). |
|
||
| `data-playback-start` | video, audio, composition | No | Source-time offset in seconds. On a nested composition, this is the child timeline time shown at the host's `data-start`. Default: `0`. |
|
||
| `data-playback-rate` | video, audio, composition | No | Source playback multiplier clamped to `0.1`–`5`. Invalid values default to `1`. |
|
||
| `data-volume` | audio, video | No | Volume level from `0` to `1`. Default: `1`. |
|
||
| `data-composition-id` | div | On compositions | Unique composition ID. Must match the key used in `window.__timelines`. |
|
||
| `data-composition-src` | div | No | Path to external composition HTML file (for [nested compositions](#composition-clips)). |
|
||
| `data-variable-values` | div | No | JSON object of values passed to a nested composition. Read via `getVariables()` in scripts, or consumed automatically by declarative bindings. |
|
||
| `data-var-src` | img, video, audio | No | Binds the element's `src` to a declared variable id — the runtime substitutes the value (URL string or image `{url}`); the authored `src` is the fallback. |
|
||
| `data-var-text` | any | No | Binds the element's own text to a scalar variable id. Element children are preserved. |
|
||
| `data-color-grading` | img, video | No | Validated JSON payload for media-level correction, grading, LUT, finishing, and shader effects. Prefer Studio or `hyperframes media-treatment` to author it. |
|
||
| `data-width` | div | On compositions | Composition width in pixels. |
|
||
| `data-height` | div | On compositions | Composition height in pixels. |
|
||
|
||
## Clip Types
|
||
|
||
<AccordionGroup>
|
||
<Accordion title="Video Clips">
|
||
Video clips embed `<video>` elements with timing and playback attributes.
|
||
|
||
```html
|
||
<video
|
||
id="el-1"
|
||
data-start="0"
|
||
data-duration="15"
|
||
data-track-index="0"
|
||
data-media-start="0"
|
||
src="./assets/video.mp4"
|
||
></video>
|
||
```
|
||
|
||
**Key behavior:**
|
||
- `data-duration` is **optional** — defaults to the remaining duration of the source file from `data-media-start`
|
||
- If source media runs out before `data-duration`, the clip shows the last frame (freeze frame)
|
||
- `data-media-start` trims the beginning of the source video — `data-media-start="5"` starts playback 5 seconds into the source file
|
||
- `data-volume` controls the audio volume of the video — set to `"0"` for silent video
|
||
- Do **not** add `class="clip"` to video elements — the framework manages their visibility directly
|
||
|
||
<Warning>
|
||
Do not animate `width`, `height`, `top`, or `left` directly on `<video>` elements with GSAP. This can cause Chrome to stop rendering video frames. Wrap the video in a `<div>` and animate the wrapper instead. See [Troubleshooting](/guides/troubleshooting).
|
||
</Warning>
|
||
</Accordion>
|
||
|
||
<Accordion title="Image Clips">
|
||
Image clips display static images with controlled timing.
|
||
|
||
```html
|
||
<img
|
||
id="el-2"
|
||
class="clip"
|
||
data-start="5"
|
||
data-duration="4"
|
||
data-track-index="1"
|
||
src="./assets/overlay.png"
|
||
/>
|
||
```
|
||
|
||
**Key behavior:**
|
||
- `data-duration` is **required** for images (unlike video/audio, there is no source duration to default to)
|
||
- `class="clip"` is **required** — this enables the runtime to show/hide the image based on timing
|
||
- Supported formats: PNG, JPG, WebP, SVG, GIF. Animated GIFs are prepared as timeline-synced video for preview and render; `data-loop` can override GIF loop metadata.
|
||
- Position and size with CSS — the image renders at its natural size unless styled otherwise
|
||
</Accordion>
|
||
|
||
<Accordion title="Audio Clips">
|
||
Audio clips add sound to the composition without any visual element.
|
||
|
||
```html
|
||
<audio
|
||
id="el-4"
|
||
data-start="0"
|
||
data-duration="30"
|
||
data-track-index="2"
|
||
src="./assets/music.mp3"
|
||
></audio>
|
||
```
|
||
|
||
**Key behavior:**
|
||
- `data-duration` is **optional** — defaults to the remaining duration of the source file from `data-media-start`
|
||
- Audio clips are invisible — do not add `class="clip"` (there is nothing to show/hide)
|
||
- `data-volume` controls volume — use `"0.5"` for background music at 50% volume
|
||
- `data-media-start` trims the beginning of the audio source, just like video
|
||
- Multiple audio clips can overlap on different tracks for layered sound design
|
||
</Accordion>
|
||
|
||
<Accordion title="Composition Clips (Nested)">
|
||
Composition clips embed one composition inside another, enabling modular, reusable video building blocks.
|
||
|
||
```html
|
||
<div
|
||
id="el-5"
|
||
data-composition-id="intro-anim"
|
||
data-composition-src="compositions/intro-anim.html"
|
||
data-start="0"
|
||
data-track-index="3"
|
||
></div>
|
||
```
|
||
|
||
**Key behavior:**
|
||
- Compositions do **not** use `data-duration` — duration is determined by the composition's GSAP timeline (`tl.duration()`)
|
||
- External compositions are loaded from `data-composition-src` and wrapped in `<template>` tags
|
||
- Each nested composition has its own `window.__timelines` entry, registered by its own `<script>` block
|
||
- The framework automatically nests sub-timelines — do not manually add them to the parent timeline
|
||
- Any composition can be nested inside any other — there is no special "root" type
|
||
- Per-instance values can be passed with `data-variable-values`; sub-composition scripts read them via `getVariables()`, and `data-var-*` bindings / `var(--id)` CSS resolve them automatically
|
||
|
||
For more on how compositions work, see [Compositions](/concepts/compositions).
|
||
</Accordion>
|
||
</AccordionGroup>
|
||
|
||
## Media Treatments
|
||
|
||
Real `<img>` and `<video>` elements may carry a `data-color-grading` payload:
|
||
|
||
```html index.html
|
||
<video
|
||
id="hero"
|
||
src="assets/hero.mp4"
|
||
data-start="0"
|
||
data-track-index="0"
|
||
muted
|
||
playsinline
|
||
data-color-grading='{
|
||
"preset":"clean-studio",
|
||
"intensity":0.8,
|
||
"adjust":{"highlights":-0.08,"shadows":0.06},
|
||
"effects":{"bloom":0.12},
|
||
"colorSpace":"rec709"
|
||
}'
|
||
></video>
|
||
```
|
||
|
||
The runtime renders the complete payload on a sibling WebGL canvas. It does not
|
||
apply to text, SVG, arbitrary DOM, or CSS background images. Use Studio or
|
||
[`media-treatment`](/packages/cli#media-treatment) for normal authoring; see
|
||
[Color Grading](/guides/color-grading) and [Media Effects](/guides/media-effects)
|
||
for the supported workflow and current SDR/HDR boundary.
|
||
|
||
## Relative Timing
|
||
|
||
Reference another clip's ID in `data-start` to mean "start when that clip ends":
|
||
|
||
```html
|
||
<video id="intro" data-start="0" data-duration="10" data-track-index="0" src="..."></video>
|
||
<video id="main" data-start="intro" data-duration="20" data-track-index="0" src="..."></video>
|
||
```
|
||
|
||
`main` starts at second 10 (when `intro` ends).
|
||
|
||
**Offsets** let you add gaps or overlaps:
|
||
|
||
```html
|
||
<!-- 2-second gap after intro -->
|
||
<video id="main" data-start="intro + 2" data-duration="20" data-track-index="0" src="..."></video>
|
||
|
||
<!-- 0.5-second overlap with intro -->
|
||
<video id="main" data-start="intro - 0.5" data-duration="20" data-track-index="0" src="..."></video>
|
||
```
|
||
|
||
For a deeper explanation, see the [relative timing section](/concepts/data-attributes#relative-timing) in the Data Attributes concept page.
|
||
|
||
## Timeline Contract
|
||
|
||
The framework initializes `window.__timelines = {}` before any scripts run. Every composition must register a GSAP timeline at the key matching its `data-composition-id`:
|
||
|
||
```javascript
|
||
const tl = gsap.timeline({ paused: true });
|
||
|
||
// Add animations
|
||
tl.to("#title", { opacity: 1, duration: 0.5 }, 0);
|
||
tl.to("#title", { opacity: 0, duration: 0.5 }, 4.5);
|
||
|
||
// Register the timeline
|
||
window.__timelines["<data-composition-id>"] = tl;
|
||
```
|
||
|
||
### Rules
|
||
|
||
- Every composition needs a `<script>` block that creates and registers its timeline
|
||
- All timelines must start paused (`{ paused: true }`)
|
||
- The framework auto-nests sub-timelines into the parent — do **not** manually add them
|
||
- Duration comes from `tl.duration()` — do **not** add `data-duration` on composition elements
|
||
- Timelines must be finite (no infinite loops or repeats)
|
||
- The timeline ID must exactly match the `data-composition-id` attribute on the root element
|
||
|
||
For a complete guide to working with GSAP timelines, see [GSAP Animation](/guides/gsap-animation).
|
||
|
||
## Caption Discoverability
|
||
|
||
For caption compositions, add these attributes to the root node so the framework can identify and special-case caption rendering:
|
||
|
||
```html
|
||
<div
|
||
data-composition-id="captions"
|
||
data-timeline-role="captions"
|
||
data-caption-root="true"
|
||
...
|
||
>
|
||
```
|
||
|
||
## Output Checklist
|
||
|
||
<Check>
|
||
Before rendering, verify your composition meets these requirements:
|
||
|
||
- Every composition has `data-width` and `data-height` on the root element
|
||
- Each reusable composition is in its own HTML file
|
||
- External compositions are loaded via `data-composition-src`
|
||
- Each external composition file uses a `<template>` wrapper
|
||
- All GSAP timelines are registered in `window.__timelines` with the correct ID
|
||
- Timed visible elements (images, divs) have `class="clip"`
|
||
- Video elements do **not** have `class="clip"` (framework manages them directly)
|
||
- All `data-start` references point to existing clip IDs
|
||
- Run `npx hyperframes lint` to catch structural issues automatically
|
||
</Check>
|