Video

import "@taprootio/espalier/video";

<esp-video>

A native video player: a <video> element with a lazy poster, a fixed aspect ratio, captions, native controls, and visible loading and error states. It is never an iframe and never loads a third-party player.

Nothing but the poster loads until the visitor presses play, so a page of videos costs one image request each. The play affordance over the poster is a real button named from label or poster-alt.

Sources

The element plays src only where the browser reports it can play type. type is an HLS master playlist by default, which Safari, iOS, and current Chrome play natively; elsewhere fallback-src (an MP4) plays instead. Espalier attaches no streaming library, so for a source every browser can play, set type="video/mp4".

Captions

Give the element <track> children. A media element only reads its own child tracks, so the element mirrors them into its video when it attaches the source; kind, srclang, label, and default carry through. With the default preload="none", no caption file loads before the visitor presses play.

Autoplay

autoplay starts playback once the element is admitted (immediately, or near the viewport with defer-offscreen). It always plays muted: while autoplay is set the video stays muted whatever muted says, so a page never starts sound unprompted. It does not start for a visitor who prefers reduced motion, or where the browser blocks it; the poster and play button remain.

Slots

<esp-video> has the following slots:

Default

<track> elements for captions, subtitles, descriptions, and chapters.

error

Replaces the error message shown over the poster.

Attributes

<esp-video> has the following attributes:

src

src has a default value of "".

The media URL: an HLS master playlist by default, or a file matching type.

type

type has a default value of "application/vnd.apple.mpegurl".

The media type of src, checked with canPlayType to choose between src and fallback-src. video/mp4 plays as a plain file.

poster

poster has a default value of "".

Poster image URL, shown until playback starts and behind error messages.

poster-alt

poster-alt has a default value of "".

Describes the poster; names the play button when label is unset.

label

label has a default value of "".

The play button's accessible name. Defaults to Play video: <poster-alt>, or Play video with no poster text.

aspect-ratio

aspect-ratio has a default value of "16 / 9".

The box's aspect ratio, as a positive number or number / number. Invalid values fall back to 16 / 9.

preload

preload has a default value of "none".

How much media to load before play intent. none (the default) loads only the poster. metadata and auto apply where the browser plays type; the choice of the fallback over it still waits for play intent. A preloaded source that fails switches to fallback-src at once.

autoplay

autoplay has a default value of false.

Start muted playback once admitted. Implies muted.

muted

muted has a default value of false.

Start muted. Always on while autoplay is set. Clearing it (or autoplay) unmutes only a paused video; a playing one stays muted until the visitor unmutes it.

loop

loop has a default value of false.

Restart from the beginning when playback ends.

playsinline

playsinline has a default value of false.

Play inline on iOS rather than entering full screen. Needed for inline autoplay there.

controls

controls has a default value of "native".

native (the default) shows the browser's controls once playback starts. none shows none; use it only for short decorative loops, since a visitor then has no way to pause.

defer-offscreen

defer-offscreen has a default value of false.

Defer everything — the poster, preload, and autoplay — until the element is within 200px of the viewport. The poster is not rendered before then, so the browser's own lazy-loading distance cannot fetch it early.

fallback-src

fallback-src has a default value of "".

An MP4 played when the browser cannot play type, and tried once when the primary source fails.

crossorigin

crossorigin has a default value of "".

CORS mode for the video's requests, as on <video crossorigin>. Needed for caption tracks served from another origin.

surface-layer

surface-layer has a default value of undefined.

Declares the painted surface depth. Fields use the next local layer, capped at layer 4.

intent

intent has a default value of undefined.

The element's intent — its meaning: neutral (no pin), or success, warning, danger, info — each pinned to its fixed status family (blue for info), retunable per theme via intents. On token-emitting controls a non-neutral intent pins the filled-action pair to that family, derived over the governing zone's theme; class-styled chrome (badges, callouts, status pills) opts out of inline emission and renders its treatment from CSS classes instead. An intent never repaints the surrounding zone, which is what contexts are for. Removing the attribute restores the element's own default intent.

context

context has a default value of undefined.

A theme-defined color zone. The selected context rebinds designer-facing roles and emits a complete, contrast-enforced semantic token table on this host for descendants to inherit.

Methods

<esp-video> has the following methods:

traverseToClosest

Traverse up the DOM tree to find the closest element that matches the selector. This method is aware of shadow DOM boundaries and will traverse through them to find the element.

Events

<esp-video> emits the following events:

esp-video-ready

esp-video-ready is of type CustomEvent<VideoReadyDetail>.

Bubbles across shadow boundaries once the attached source has loaded its metadata; detail is { src, mode, duration }. Fires once per attached source.

esp-video-play

esp-video-play is of type CustomEvent<VideoPlayDetail>.

Bubbles across shadow boundaries each time playback starts, or resumes after a pause, on the media's playing. Recovery from buffering or a seek is not reported, and a source that fails first reports no play; detail is { src, mode, currentTime, autoplay }.

esp-video-error

esp-video-error is of type CustomEvent<VideoErrorDetail>.

Bubbles across shadow boundaries when a source fails; detail is { src, mode, reason, message, fallback }. When fallback is true the element is already trying fallback-src.

CSS Parts

<esp-video> has the following CSS parts:

frame

The element's full box.

video

The native <video> element.

poster

The layer over the video holding the poster, play button, and messages.

poster-image

The poster <img>.

play

The play <button>, which covers the poster.

play-icon

The visible play disc inside the button.

message

The error message.

CSS Properties

<esp-video> has the following CSS properties:

--esp-video-surface

Background behind the video and an absent poster. Defaults to a near-black derived from --esp-color-text.

--esp-video-border-radius

Corner radius. Defaults to var(--esp-size-border-radius).

--esp-video-object-fit

How the video fills its box. Defaults to contain; the poster always covers.

--esp-video-accent

accent-color for the native controls, where the browser honors it. Defaults to var(--esp-color-primary).

--esp-video-focus-outline

Focus-visible outline on the play button, the video, and the error message. Defaults to 3px solid var(--esp-color-link).

--esp-video-play-size

Diameter of the play disc. Defaults to var(--esp-size-huge).

--esp-video-play-background

Fill of the play disc. Defaults to var(--esp-color-background) at 90% opacity.

--esp-video-play-color

Play glyph and loading-indicator color. Defaults to var(--esp-color-text).

--esp-video-message-background

Error message background. Defaults to var(--esp-color-background).

--esp-video-message-color

Error message text color. Defaults to var(--esp-color-text).

--esp-field-background

Background color of the shared field shell. Defaults to one layer above the nearest declared surface, capped at var(--esp-color-layer-4), or var(--esp-color-layer-2) without a declared surface. An explicit override wins.

--esp-field-border-color

Border color of the shared field shell. Defaults to var(--esp-color-border).

--esp-field-border-width

Border width of the shared field shell. Defaults to 1px.

--esp-field-text-color

Text color used inside the shared field shell. Defaults to var(--esp-color-text).

--esp-field-hover-bg

Hover background color of the shared field shell. Derived from --esp-field-background.

--esp-field-focus-bg

Focus background color of the shared field shell. Derived from --esp-field-background.

--esp-field-focus-shadow

Shadow color used for shared field focus treatment. Defaults to var(--esp-color-shadow).

Components API Guides Getting started Styling Espalier Browser support GitHub npm package Taproot I/O