Overview
HyperFrames uses HTML as the source of truth for describing a video:- HTML clips = video, image, audio, composition
- Data attributes = timing, metadata, styling
- CSS = positioning and appearance
- GSAP timeline = animations and playback sync (see GSAP Animation)
Framework-Managed Behavior
The framework reads data attributes and automatically manages:- Primitive clip timeline entries — reads
data-start,data-duration, anddata-track-indexfrom 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-startanddata-duration - Timeline synchronization — keeps media in sync with the GSAP master timeline
- Media loading — waits for all media to load before resolving timing
Viewport
Every composition must includedata-width and data-height on the root element:
- Landscape:
data-width="1920" data-height="1080" - Portrait:
data-width="1080" data-height="1920"
All Clip Attributes
Clip Types
Video Clips
Video clips embed<video> elements with timing and playback attributes.
data-durationis optional — defaults to the remaining duration of the source file fromdata-media-start- If source media runs out before
data-duration, the clip shows the last frame (freeze frame) data-media-starttrims the beginning of the source video —data-media-start="5"starts playback 5 seconds into the source filedata-volumecontrols 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
Image Clips
Image clips display static images with controlled timing.data-durationis 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-loopcan override GIF loop metadata. - Position and size with CSS — the image renders at its natural size unless styled otherwise
Audio Clips
Audio clips add sound to the composition without any visual element.data-durationis optional — defaults to the remaining duration of the source file fromdata-media-start- Audio clips are invisible — do not add
class="clip"(there is nothing to show/hide) data-volumecontrols volume — use"0.5"for background music at 50% volumedata-media-starttrims the beginning of the audio source, just like video- Multiple audio clips can overlap on different tracks for layered sound design
Composition Clips (Nested)
Composition clips embed one composition inside another, enabling modular, reusable video building blocks.- Compositions do not use
data-duration— duration is determined by the composition’s GSAP timeline (tl.duration()) - External compositions are loaded from
data-composition-srcand wrapped in<template>tags - Each nested composition has its own
window.__timelinesentry, 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 viagetVariables(), anddata-var-*bindings /var(--id)CSS resolve them automatically
Media Treatments
Real<img> and <video> elements may carry a data-color-grading payload:
index.html
media-treatment for normal authoring; see
Color Grading and Media Effects
for the supported workflow and current SDR/HDR boundary.
Relative Timing
Reference another clip’s ID indata-start to mean “start when that clip ends”:
main starts at second 10 (when intro ends).
Offsets let you add gaps or overlaps:
Timeline Contract
The framework initializeswindow.__timelines = {} before any scripts run. Every composition must register a GSAP timeline at the key matching its data-composition-id:
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 adddata-durationon composition elements - Timelines must be finite (no infinite loops or repeats)
- The timeline ID must exactly match the
data-composition-idattribute on the root element
Caption Discoverability
For caption compositions, add these attributes to the root node so the framework can identify and special-case caption rendering:Output Checklist
Before rendering, verify your composition meets these requirements:
- Every composition has
data-widthanddata-heighton 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.__timelineswith the correct ID - Timed visible elements (images, divs) have
class="clip" - Video elements do not have
class="clip"(framework manages them directly) - All
data-startreferences point to existing clip IDs - Run
npx hyperframes lintto catch structural issues automatically