Customize skins
Style a packaged Video.js skin or copy its source to change controls, layout, styles, and interactions
Start with the path that matches the change you want:
| If you want to… | Use this path |
|---|---|
| Change colors, typography, sizing, or how the poster fills the player | Style a packaged skin. The skin stays in the Video.js package, and you set its supported CSS properties. |
| Add, remove, rearrange, or deeply restyle controls; change layout or interactions | Eject and edit a skin. Ejecting copies the skin’s source files into your project so you can change them. |
Style a packaged skin
Use a packaged skin’s public settings to match it to your site without copying its source into your project.
Set the skin’s styles
Packaged skins expose CSS custom properties for their supported visual changes. Set them on the skin or any element that contains it:
<video-skin style="--media-accent-color: #f5c518; --media-border-radius: 1rem">
<video src="video.mp4"></video>
</video-skin><VideoSkin
style={
{
'--media-accent-color': '#f5c518',
'--media-border-radius': '1rem',
} as React.CSSProperties
}
>
<Video src="video.mp4" />
</VideoSkin>| Property name | What it changes | Value | Example |
|---|---|---|---|
--media-accent-color |
Slider fills, highlighted controls and menu items, and primary actions | <color> |
#f5c518 |
--media-accent-text-color |
Text and icons shown on the accent color | <color> |
black |
--media-border-color |
The hairline around the player | <color> |
transparent |
--media-border-radius |
The player corner radius | A valid border-radius value | 1rem |
--media-font-family |
The player interface font stack | A valid font-family value | Roboto, sans-serif |
--media-object-fit |
How the media and poster fill the player | A valid object-fit value | cover |
--media-object-position |
Where the media and poster sit when they do not fill the player | A valid object-position value | top |
--media-scale-unit |
The base size for skin spacing, icons, and text | <length> |
1rem |
If you omit --media-accent-text-color, the skins choose a contrasting text color from --media-accent-color using contrast-color(). Set it only when you want a different result.
The skins use Inter when your page loads it and fall back to the system UI font. Video.js does not load the webfont for you. Set --media-font-family to use another font.
The media element and poster share --media-object-fit and --media-object-position, so a cover poster stays aligned with cover video. See Add a poster and loading placeholder.
Set the color scheme
The audio skins adapt their main palette for light and dark mode using light-dark(). They read the inherited color-scheme, so set it on the player or an element that contains it:
:root {
color-scheme: light dark;
}The video skins keep their dark controls in both color schemes. Only their hairline border follows the scheme, and --media-border-color replaces it.
Scale from the document font size
The skins derive control spacing, icon sizes, and text from --media-scale-unit. It defaults to 16px, so the player does not change with the document root font size or your app’s Tailwind spacing scale. Set it to 1rem to make the interface scale from the document root font size:
.player {
--media-scale-unit: 1rem;
}In fullscreen, the skins increase the unit up to 1.75 times on displays 1920 pixels and wider. This keeps controls legible from a distance.
You can also add your own class names to the skins.
Know where packaged styling stops
The properties above are the public styling settings for packaged skins. Do not depend on the elements, class names, or other custom properties inside a packaged skin. They may change between releases.
Packaged video skins also let you replace the poster through the poster slot.
Packaged video skins also let you replace the poster through the renderPoster prop.
See Poster.
Packaged skins do not provide settings for adding, removing, or rearranging controls, or for replacing built-in feedback and interactions. To make those changes, eject the closest skin and edit its source.
Eject and edit a skin
If a packaged skin is close to the interface you want, eject it and edit the copy in your project. Ejecting turns the skin’s controls, layout, styles, and interactions into app code that you own.
Video.js publishes the skin source in a catalog of installable files. The shadcn CLI is the command-line tool that copies those files into your project, whether you use React or HTML.
Set up the shadcn CLI
If your project does not have a components.json configuration file, create one:
npx shadcn@latest initpnpm dlx shadcn@latest inityarn dlx shadcn@latest initbunx --bun shadcn@latest initChoose how the skin is styled
Each React skin is available with Tailwind CSS 4 classes or with a plain stylesheet, labeled Vanilla CSS. Choose the form your project uses. Skin names stay the same.
HTML skins use plain stylesheets, labeled Vanilla CSS. Each skin includes markup that renders directly in the page, a module that registers its custom elements, and a stylesheet.
HTML skins install as vanilla CSS.
Connect the CLI to Video.js
Run this command once. It saves @videojs as a short prefix in components.json, so later commands can use names such as @videojs/video:
npx shadcn@latest registry add @videojs=https://shadcn.videojs.org/r/html/{name}.jsonpnpm dlx shadcn@latest registry add @videojs=https://shadcn.videojs.org/r/html/{name}.jsonyarn dlx shadcn@latest registry add @videojs=https://shadcn.videojs.org/r/html/{name}.jsonbunx --bun shadcn@latest registry add @videojs=https://shadcn.videojs.org/r/html/{name}.jsonInstall a skin
Install the skin closest to the interface you want. Default skins use the preset name, and Minimal skins add -minimal:
npx shadcn@latest add @videojs/videopnpm dlx shadcn@latest add @videojs/videoyarn dlx shadcn@latest add @videojs/videobunx --bun shadcn@latest add @videojs/video| Skin | Install name | Installs to |
|---|---|---|
| Default Video | @videojs/video | components/videojs/skins/video |
| Minimal Video | @videojs/video-minimal | components/videojs/skins/video/minimal |
| Default Audio | @videojs/audio | components/videojs/skins/audio |
| Minimal Audio | @videojs/audio-minimal | components/videojs/skins/audio/minimal |
| Default Live Video | @videojs/live-video | components/videojs/skins/live-video |
| Minimal Live Video | @videojs/live-video-minimal | components/videojs/skins/live-video/minimal |
| Default Live Audio | @videojs/live-audio | components/videojs/skins/live-audio |
| Minimal Live Audio | @videojs/live-audio-minimal | components/videojs/skins/live-audio/minimal |
The paths in the table start from the component location configured in components.json. The background video skin cannot be ejected.
Use the installed skin
The skin’s files are under components/videojs/skins/<preset>. Keep importing the player and media from @videojs/react. Import the installed skin component from skin.tsx, then render it around your media where you previously rendered the packaged skin.
The skin’s files are under components/videojs/skins/<preset>. Keep importing the player and media from @videojs/html. Import the installed skin.ts once, then paste the markup from skin.html inside your player around the media element.
Edit the installed files
Start with the file that owns the change you want:
| Goal | Where to start |
|---|---|
| Add, remove, or rearrange controls | skin.tsx in React or skin.html in HTML |
| Change colors, surfaces, shadows, sizes, or motion across the skin | components/videojs/styles/theme.css |
| Change one control’s appearance | That control’s classes or stylesheet |
| Change one control’s interaction | That control’s module |
The files for the control bar, gestures, keyboard shortcuts, settings menu, and status indicators are composed from skin.tsx. The UI components they use are installed as source too, so you can open and change each button or slider.
- Tailwind CSS. Components use utility classes. The install adds the theme keys, utilities, and variants to your main CSS file. The skins require Tailwind CSS 4.3 or later and its default configuration. If your project prefixes Tailwind classes, update the installed components.
- Vanilla CSS. Components use class names that start with
media-, and the skin’sskin.cssstylesheet styles them.
The skin.html file contains the layout. The skin.ts module registers the custom elements and loads skin.css. Elements use class names that start with media-; change a class in skin.html or a rule in the stylesheet to change one part of the interface.
Inspect or update an ejected skin
Use the CLI’s search command to find source and view to inspect it before installation:
npx shadcn@latest search @videojs --query volume
npx shadcn@latest view @videojs/videoInstalled files belong to your project, so an update replaces your local copy. Commit your changes, reinstall with --overwrite, and review the resulting version-control diff before keeping it:
npx shadcn@latest add @videojs/video --overwriteTo understand how skins fit into Video.js, read Skins. To create a control instead of editing one, follow Build your own component.