Dev Tools
SanityVideo
Plays a silent, looping, controls-free video uploaded to Sanity. The video counterpart to FigmaImage — same layout props (ratio, variant, fit, radius, description), lazy-loaded and reduced-motion aware.
Import
import SanityVideo from '../../components/utility/SanityVideo.astro'; Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | Yes | — | Looks up a brandVideo document by its name field |
ratio | '16:9' | '1:1' | '3:2' | '4:3' | No | '16:9' | Fixed aspect ratio. Always set (videos carry no dimension metadata) to prevent layout shift |
variant | 'full' | 'half' | 'third' | 'quarter' | No | 'full' | Width relative to content column |
fit | 'crop' | 'fill' | 'contain' | 'cover' | No | 'cover' | How the video fills the frame. crop/cover fill and crop overflow; contain letterboxes |
alt | string | No | doc altText | Accessible label. Falls back to the document's alt text; pass "" for decorative clips |
radius | 0 | 4 | 6 | 8 | 10 | 12 | 16 | 20 | 24 | 32 | No | 16 | Corner radius token. Defaults to --primitive-radius-16 |
description | string | No | — | Centered caption below the video — body-sm, secondary color. Same convention as FigmaImage |
Usage
<!-- Basic -->
<SanityVideo id="brand-shapes-hero" alt="Shapes morphing loop" />
<!-- Square, half width -->
<SanityVideo id="brand-shapes-hero" ratio="1:1" variant="half" alt="Shapes loop" />
<!-- With caption -->
<SanityVideo id="brand-shapes-hero" description="Shapes in motion" alt="Shapes loop" />
<!-- Inside Columns -->
<Columns count={2}>
<SanityVideo id="clip-a" description="First clip" />
<SanityVideo id="clip-b" description="Second clip" />
</Columns> Preparing a video
Compress locally first, then upload in Sanity Studio. Strip audio, cap the resolution, and encode both formats. WebM (VP9) is served first; MP4 (H.264) is the universal fallback.
# 1. MP4 (H.264) — universal fallback. +faststart enables progressive playback.
ffmpeg -i input.mov -an -vf "scale='min(1280,iw)':-2" \
-c:v libx264 -profile:v high -pix_fmt yuv420p -crf 24 -preset slow \
-movflags +faststart output.mp4
# 2. WebM (VP9) — smaller; served first to modern browsers.
ffmpeg -i input.mov -an -vf "scale='min(1280,iw)':-2" \
-c:v libvpx-vp9 -crf 32 -b:v 0 -row-mt 1 output.webm
# 3. Poster — first-frame still (required).
ffmpeg -i input.mov -frames:v 1 -q:v 2 poster.jpg -anstrips the audio track (clips are always silent).scale='min(1280,iw)':-2caps width at 1280px and keeps the aspect ratio (never upscales).- Higher
-crf= smaller file, lower quality. Tune H.264 ~23–28 and VP9 ~30–34 to taste.
Uploading to Sanity
- Open Sanity Studio → Brand Video → create a new document.
- Set Name (ID) to the value you pass as
id(lowercase, hyphenated, unique). - Upload the WebM, MP4, and Poster files, fill in Alt Text, and publish.
- Reference it in a page:
<SanityVideo id="your-name" />.
Preview — fallback (no video uploaded)
When no matching brandVideo document exists, a neutral surface placeholder is shown. Once a clip is uploaded with a matching name, it renders here.
Preview — 2 columns (text + 1:1 video)
<Columns count={2}>
<TextSection variant="card" heading="Placeholder heading">
<p>Placeholder copy goes here...</p>
</TextSection>
<SanityVideo id="brand-shapes-loop" ratio="1:1" alt="Shapes loop" />
</Columns> Placeholder heading
This is placeholder copy. It sits next to the video to show how a two-column layout pairs a text block with a square clip. Swap it for real content when you use the component.
The 1:1 frame keeps its square shape and sets the row height; the text column matches it. (Shown here as the placeholder, since no clip is uploaded — a real square video renders in the same box.)
Preview — 3 columns (1:1 videos)
<Columns count={3}>
<SanityVideo id="clip-a" ratio="1:1" alt="..." />
<SanityVideo id="clip-b" ratio="1:1" alt="..." />
<SanityVideo id="clip-c" ratio="1:1" alt="..." />
</Columns> Three squares in a row, each filling a third of the width. Same ratio → equal height with no cropping.
Preview — 3 columns (4:3 videos)
Preview — 2 columns (text + 4:3 video)
Placeholder heading
This is placeholder copy beside a 4:3 clip. The 4:3 frame keeps its shape and sets the row height; the text column matches it.
Notes
- Playback is locked:
loop+muted+playsinline, no controls, no audio. - Clips are lazy:
preload="none"plus an IntersectionObserver — a video only downloads and plays once scrolled into view, and pauses when it leaves. - Respects
prefers-reduced-motion— reduced-motion users see the poster still instead of motion. - A poster (first-frame still) is required and always renders first, so there is no blank flash before load.
- Unlike FigmaImage, there is no Figma sync — videos are uploaded to Sanity directly and looked up by the document's
namefield. - Works inside
Columnsat any count (2–4). Each clip keeps its aspect ratio and drives the row height — a row of same-ratio clips (e.g. three 1:1 or three 4:3) stays equal height with no cropping. - Served from Sanity's file CDN as-uploaded (no transcoding) — which is why compressing well before upload matters.