# Video.js v10 — HTML Components (complete)
> Every HTML components page in one file (about 115k tokens). Index with descriptions: https://videojs.org/docs/framework/html/reference/components/llms.txt
---
# video-player
The state boundary — creates a store and broadcasts it to all descendants.
The `` element is the state boundary of your player. It creates a store and makes it available to every element inside it via context. Every player needs exactly one.
```html
```
## How it’s created
For most users, importing from `@videojs/html/video/player` registers a ready-to-use `` element with the standard video [features](https://videojs.org/docs/framework/html/guides/features) (bundled as a [preset](https://videojs.org/docs/framework/html/guides/presets)):
```ts
import '@videojs/html/video/player';
```
```html
```
If you need a custom feature set or tag name, use `createPlayer()` to get the configured `PlayerElement`. Extend `ContainerElement` separately when you need custom container behavior:
**my-player.ts**
```ts
import { ContainerElement, createPlayer } from '@videojs/html';
import { videoFeatures } from '@videojs/html/video';
const { PlayerElement: MyPlayer } = createPlayer({ features: videoFeatures });
class MyContainer extends ContainerElement {}
customElements.define('my-player', MyPlayer);
customElements.define('my-container', MyContainer);
```
- [`createPlayer` reference](https://videojs.org/docs/framework/html/reference/api/html-create-player)
## What lives inside it
Everything that needs player state goes inside ``: skins, containers, UI components, and your own custom components. Anything inside can access the store.
```html
```
## No visual presence
Packaged skins make `` boxless with `display: contents`. Width, height, positioning, transforms, and `getBoundingClientRect()` do not describe a visible player box there. Put layout and measurements on the [``](https://videojs.org/docs/framework/html/reference/components/player-container) instead.
If you omit `` and import only the player and media components, those skin styles are not loaded. The player element still owns state, not layout, so add and style a `` instead of using the player itself as the layout surface.
## Accessing state
Use the preset’s typed `PlayerController` to subscribe to store state from any custom element inside the player:
**play-pause-button.ts**
```ts
import { UIElement, selectPlayback } from '@videojs/html';
import { PlayerController } from '@videojs/html/video';
class PlayPauseButton extends UIElement {
readonly #playback = new PlayerController(this, selectPlayback);
connectedCallback() {
super.connectedCallback();
this.addEventListener('click', this.#togglePlayback);
}
disconnectedCallback() {
this.removeEventListener('click', this.#togglePlayback);
super.disconnectedCallback();
}
readonly #togglePlayback = () => {
const playback = this.#playback.value;
if (!playback) return;
playback.paused ? playback.play() : playback.pause();
};
}
customElements.define('play-pause-button', PlayPauseButton);
```
- [PlayerController reference](https://videojs.org/docs/framework/html/reference/api/player-controller)
## Extended player layouts
The player’s scope can extend beyond the fullscreen target. Playlists, transcripts, sidebars, and other supplementary UI can live inside `` but outside ``. They still have full access to the store, but they won’t go fullscreen with the video.
```html
...
```
## Lifecycle
Video.js elements clean up after themselves when you remove them from the page:
- `` and the UI elements destroy themselves two animation frames after they’re removed. Destroying the player also destroys its store.
- Media components such as `` tear down their playback engine in a microtask after they’re removed.
Moving an element synchronously, removing it and inserting it elsewhere with no `await` in between, triggers neither. To keep an element through a longer move, add the `keep-alive` attribute:
```html
```
`keep-alive` applies only to the element that carries it; descendants don’t inherit it. Set it on every Video.js element in the tree you move. Packaged skins don’t pass it to the controls inside them, so move a player that uses a packaged skin synchronously. An element with `keep-alive` is never destroyed automatically. When you’re finished with it, call `destroy()` on the player and UI elements, and `adapter.destroy()` on media components, which release their engine that way. A destroyed element can’t be reconnected; create a new one instead.
---
# media-container
The player's visual and interaction surface for layout, fullscreen, focus, and user activity.
The `` is the player’s physical surface. It defines the visual boundary, registers the fullscreen and activity target, and gives gesture and hotkey elements a shared interaction surface. It lives inside a [``](https://videojs.org/docs/framework/html/reference/components/player).
```html
...
```
## How it’s created
Import the standard player entry point and the container. `video/player` registers only ``; `ui/container` registers ``:
```ts
import '@videojs/html/video/player';
import '@videojs/html/ui/container';
```
```html
```
For custom behavior, extend the same `ContainerElement` used by the built-in player:
**my-player.ts**
```ts
import { ContainerElement } from '@videojs/html';
class MyContainer extends ContainerElement {}
customElements.define('my-container', MyContainer);
```
Extending `ContainerElement` automatically registers the element with the nearest player when it connects and releases that registration when it disconnects.
Import `@videojs/html/ui/container` when you only need to register the standard `` element.
## 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 ``, not ``. Place overlays inside it, use it as their positioning context, and measure it when your app needs the rendered player size.
```css
.player-surface {
position: relative;
display: block;
width: 640px;
aspect-ratio: 16 / 9;
}
```
```html
...
```
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.
Custom video elements such as `` and `` do not create their own layout boxes: their inner `