Skip to content
FrameworkStyle

Container

The player's visual and interaction surface for layout, fullscreen, focus, and user activity.

The Container is the player’s physical surface. It defines the visual boundary, registers the fullscreen and activity target, and gives gesture and hotkey components a shared interaction surface. It lives inside a Player.

<Player>
  <Container>
    <Video src="video.mp4" />
    <Controls.Root>
      <Controls.Content>{/* ... */}</Controls.Content>
    </Controls.Root>
  </Container>
</Player>

How it’s created

Import Container from the main React package. It connects to whichever Player contains it, so it does not need to be created for a specific feature set.

import { Container, createPlayer } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

const { Player } = createPlayer({ features: videoFeatures });

What it does

Layout and fullscreen

The container is the visual box around your media and controls. Put sizing, aspect ratio, positioning, and visual boundaries here — on Container, not Player. Place overlays inside it, use it as their positioning context, and measure it when your app needs the rendered player size.

<Container style={{ position: 'relative', width: 640, aspectRatio: '16/9' }}>
  <Video src="video.mp4" />
  <Controls.Root>
    <Controls.Content>{/* ... */}</Controls.Content>
  </Controls.Root>
</Container>

When the user goes fullscreen, the container goes fullscreen — not the video element. This keeps controls and other UI visible on top of the video, since they’re children of the container.

React media components such as MuxVideo render a native media element, so the media itself has a box. The container remains the shared layout and fullscreen target for the media and its overlays.

Media attachment

Media discovery is handled by Player, not Container. When a media component like <Video> registers itself via context, Player wires it to the store and all of the player’s features.

Interaction surface

The container is where user intent enters the player. It listens for physical interaction on its surface and translates that into player behavior:

  • User activity — Mouse movement, touch, and keyboard activity within the container drive idle detection. This is how controls know when to show and hide.
  • Gestures — Tap and double-tap actions, optionally limited by pointer type and left, center, or right region. Configured via the Gesture component.
  • Keyboard controls — Spacebar to play/pause, arrow keys to seek, and other keyboard shortcuts scoped to the container. Configured via the Hotkey component.

Each container owns one popup group. Opening a root menu or popover closes the previously open popup in that container. A popup rendered outside the container still manages its own open state, but it does not participate in the container’s group.

Relationship to skins

A skin is a container plus UI controls. When you use a packaged skin, the container is built in — you don’t need to add one yourself.

Style VideoSkin for the player’s outer size and aspect ratio. Its skin.css import makes the built-in container fill that space and positions the media, controls, poster, and overlays.

If you omit VideoSkin to build custom UI, render and style Container yourself. See Layout and fullscreen for the complete layout example.

Inside vs. outside the container

Player gives components access to state and actions. Container layers on physical behaviors — fullscreen, activity detection, and gesture handling. Components work in both places; the container just adds those extras.

<Player>
  <Container>
    <Video src="video.mp4" />
    <Controls.Root>          {/* fullscreen, activity detection, gestures */}
      <Controls.Content>{/* ... */}</Controls.Content>
    </Controls.Root>
  </Container>

  <Transcript />          {/* state & actions, but no container behaviors */}
  <PlaylistSidebar />     {/* state & actions, but no container behaviors */}
</Player>

A play button outside the container still reads playback state and can toggle play/pause — it just won’t go fullscreen with the player or respond to the container’s idle state.