FrameworkStyle

UI components

How Video.js UI components work — one element per component, data attributes for state, and compound composition.

UI components are controls like buttons, sliders, and time displays.

Every UI component renders exactly one HTML element, taking inspiration from projects like shadcn/ui and Base UI. This approach gives you control over styling and behavior while handling the complex interactions for you.

Where to put your components

UI Components can go anywhere inside a <video-player>.

However, you should consider placing your components in <player-container>. Components in <player-container> will go fullscreen with the player, respond to user activity, and more.

Styling and customization

Components reflect player state as data-* attributes on their element. For example, data-paused or data-volume-level="high".

This lets you style state changes in pure CSS:

<media-play-button class="my-play-button">
  <span class="play-icon">Play</span>
  <span class="pause-icon">Pause</span>
</media-play-button>
media-play-button .play-icon  { display: none; }
media-play-button .pause-icon { display: none; }

media-play-button[data-paused] .play-icon        { display: inline; }
media-play-button:not([data-paused]) .pause-icon  { display: inline; }

Each component’s reference page documents its full set of data attributes.

Some components also expose CSS custom properties for continuous values like fill percentage and pointer position. Sliders, for example, set --media-slider-fill and --media-slider-pointer. See individual component reference pages for specifics.

Compound components

Complex interactions are split into composable parts. A parent manages shared state while children consume it. Each part is still one element.

<media-volume-slider orientation="vertical">
  <media-slider-track>
    <media-slider-fill></media-slider-fill>
  </media-slider-track>
  <media-slider-thumb></media-slider-thumb>
</media-volume-slider>