Skip to content

docs(skin): add docs on skin styling#958

Merged
sampotts merged 1 commit intomainfrom
docs/skin-styling
Mar 20, 2026
Merged

docs(skin): add docs on skin styling#958
sampotts merged 1 commit intomainfrom
docs/skin-styling

Conversation

@sampotts
Copy link
Copy Markdown
Collaborator

@sampotts sampotts commented Mar 16, 2026

Summary

  • Add skin styling guidance covering packaged vs ejected usage, vanilla CSS vs Tailwind, and current styling limitations.
  • Document basic skin customization with CSS custom properties and clarify the ejecting workflow for default and minimal skins.
  • Add installation guidance for CSP requirements and link the installation flow back to the skin styling docs.

Testing

  • Not run (documentation-only changes).

Closes #674

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v10-sandbox Ready Ready Preview, Comment Mar 20, 2026 3:35am

Request Review

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 16, 2026

Deploy Preview for vjs10-site failed. Why did it fail? →

Name Link
🔨 Latest commit 3701f82
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/69bcb61d8f006f000720a4c9

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 16, 2026

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Size
/video (default) 23.22 kB
/video (default + hls) 153.63 kB
/video (minimal) 23.05 kB
/video (minimal + hls) 153.68 kB
/audio (default) 21.46 kB
/audio (minimal) 21.44 kB
/background 6.38 kB
Media (5)
Entry Size
/media/background-video 1.03 kB
/media/container 1.59 kB
/media/dash-video 236.04 kB
/media/hls-video 131.57 kB
/media/simple-hls-video 12.33 kB
Players (3)
Entry Size
/video/player 6.24 kB
/audio/player 6.23 kB
/background/player 6.22 kB
Skins (16)
Entry Type Size
/video/minimal-skin.css css 3.12 kB
/video/skin.css css 3.15 kB
/video/minimal-skin js 22.25 kB
/video/minimal-skin.tailwind js 22.50 kB
/video/skin js 22.42 kB
/video/skin.tailwind js 22.76 kB
/audio/minimal-skin.css css 2.28 kB
/audio/skin.css css 2.30 kB
/audio/minimal-skin js 20.66 kB
/audio/minimal-skin.tailwind js 20.70 kB
/audio/skin js 20.68 kB
/audio/skin.tailwind js 20.94 kB
/background/skin.css css 117 B
/background/skin js 1003 B
/base.css css 157 B
/shared.css css 86 B
UI Components (21)
Entry Size
/ui/alert-dialog 2.08 kB
/ui/alert-dialog-close 1.63 kB
/ui/alert-dialog-description 1.52 kB
/ui/alert-dialog-title 1.55 kB
/ui/buffering-indicator 1.78 kB
/ui/captions-button 1.79 kB
/ui/controls 1.59 kB
/ui/fullscreen-button 1.81 kB
/ui/mute-button 1.78 kB
/ui/pip-button 1.80 kB
/ui/play-button 1.82 kB
/ui/playback-rate-button 1.81 kB
/ui/popover 3.27 kB
/ui/poster 1.75 kB
/ui/seek-button 1.80 kB
/ui/slider 2.02 kB
/ui/thumbnail 2.12 kB
/ui/time 1.68 kB
/ui/time-slider 2.12 kB
/ui/tooltip 2.40 kB
/ui/volume-slider 2.26 kB

Sizes are marginal over the root entry point.

⚛️ @videojs/react — no changes
Presets (7)
Entry Size
/video (default) 19.00 kB
/video (default + hls) 149.82 kB
/video (minimal) 19.03 kB
/video (minimal + hls) 149.71 kB
/audio (default) 14.93 kB
/audio (minimal) 15.05 kB
/background 3.13 kB
Media (4)
Entry Size
/media/background-video 476 B
/media/dash-video 236.19 kB
/media/hls-video 131.59 kB
/media/simple-hls-video 12.34 kB
Skins (14)
Entry Type Size
/video/minimal-skin.css css 3.12 kB
/video/skin.css css 3.15 kB
/video/minimal-skin js 18.93 kB
/video/minimal-skin.tailwind js 22.13 kB
/video/skin js 18.95 kB
/video/skin.tailwind js 22.14 kB
/audio/minimal-skin.css css 2.28 kB
/audio/skin.css css 2.30 kB
/audio/minimal-skin js 14.94 kB
/audio/minimal-skin.tailwind js 17.02 kB
/audio/skin js 14.88 kB
/audio/skin.tailwind js 17.25 kB
/background/skin.css css 90 B
/background/skin js 272 B
UI Components (18)
Entry Size
/ui/alert-dialog 2.24 kB
/ui/buffering-indicator 2.21 kB
/ui/captions-button 2.25 kB
/ui/controls 2.24 kB
/ui/fullscreen-button 2.27 kB
/ui/mute-button 2.26 kB
/ui/pip-button 2.27 kB
/ui/play-button 2.24 kB
/ui/playback-rate-button 2.27 kB
/ui/popover 2.87 kB
/ui/poster 2.08 kB
/ui/seek-button 2.27 kB
/ui/slider 3.17 kB
/ui/thumbnail 2.01 kB
/ui/time 1.93 kB
/ui/time-slider 2.65 kB
/ui/tooltip 2.69 kB
/ui/volume-slider 2.68 kB

Sizes are marginal over the root entry point.

🧩 @videojs/core — no changes
Entries (6)
Entry Size
. 4.81 kB
/dom 8.41 kB
/dom/media/custom-media-element 1.81 kB
/dom/media/dash 235.62 kB
/dom/media/hls 131.27 kB
/dom/media/simple-hls 11.85 kB
🏷️ @videojs/element — no changes
Entries (2)
Entry Size
. 999 B
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Size
. 1.32 kB
/html 700 B
/react 360 B
🔧 @videojs/utils — no changes
Entries (10)
Entry Size
/array 104 B
/dom 1.25 kB
/events 227 B
/function 261 B
/object 119 B
/predicate 265 B
/string 148 B
/style 190 B
/time 478 B
/number 158 B
📦 @videojs/spf — no changes
Entries (3)
Entry Size
. 40 B
/dom 10.04 kB
/playback-engine 9.94 kB

ℹ️ How to interpret

All sizes are standalone totals (minified + brotli).

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the documentation around skin styling and customization, and links installation guidance to the new styling docs, addressing the styling documentation gap from issue #674.

Changes:

  • Add CSP guidance to the installation docs and link readers to the skins styling section.
  • Expand “Customize skins” with basic CSS custom-property customization guidance and clarify the “ejecting” workflow.
  • Add a new “Styling” section to the Skins concept doc, covering vanilla CSS vs Tailwind and current limitations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
site/src/content/docs/how-to/installation.mdx Adds CSP notes and links installation readers to skins styling documentation.
site/src/content/docs/how-to/customize-skins.mdx Adds basic customization via CSS variables and refines the ejecting instructions/examples.
site/src/content/docs/concepts/skins.mdx Adds a styling section (vanilla CSS vs Tailwind), limitations, and simplifies ejected examples via EjectedSkin.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread site/src/content/docs/how-to/customize-skins.mdx
Comment on lines +133 to +145
- `style-src 'unsafe-inline'` is currently required for some player UI and HTML player styling behavior.

### Example

```http
Content-Security-Policy:
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' https: data: blob:;
media-src 'self' https: blob:;
connect-src 'self' https:;
worker-src 'self' blob:;
```
Comment thread site/src/content/docs/concepts/skins.mdx Outdated
Comment on lines +122 to +145
## CSP

If your application uses a Content Security Policy, you may need to allow additional sources for player features to work correctly.

### Common requirements

- `media-src` must allow your media URLs.
- `img-src` must allow any poster or thumbnail image URLs.
- `connect-src` must allow HLS manifests, playlists, captions, and segment requests when using HLS playback.
- `media-src blob:` is required when using the HLS player variants, which use MSE-backed playback.
- `worker-src blob:` is required when using the `hls.js` player variants.
- `style-src 'unsafe-inline'` is currently required for some player UI and HTML player styling behavior.

### Example

```http
Content-Security-Policy:
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' https: data: blob:;
media-src 'self' https: blob:;
connect-src 'self' https:;
worker-src 'self' blob:;
```
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion(non-blocking): installation is a very tight guide. We should consider moving this CSP section to a new security guide (#966) and linking out.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we can add some more details there about unsafe-inline if we continue with inline styles. I have an RFC in the works for moving to scoped <style> blocks instead.

Comment on lines +147 to +149
## Styling

See the [skins styling](../concepts/skins#styling) section.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

polish(non-blocking): consider using DocsLinkCard here, like we do in overview.

Maybe, combined with my security comment up above, this section could be something like

## See also
<DocsLinkCard slug="concepts/skins" anchor="styling" description="Some skins expose CSS custom properties">Skins</DocsLinkCard>
<DocsLinkCard slug="concepts/skins" anchor="styling" description="If you have a content security policy (CSP), you may need to enable additional sources">Security</DocsLinkCard>

This would require adding an anchor prop to DocsLinkCard and the underlying DocsLink.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave out the security page there as I think we need to talk through nonce and unsafe-inline stuff first.

import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';
import Aside from '@/components/Aside.astro';

import EjectedSkin from '@/components/docs/EjectedSkin.astro';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call!

Comment on lines +13 to +16
| Property Name | Description | Type | Example |
| ------------- | ----------- | ---- | ------- |
| `--media-border-radius` | The border radius of the media player | A valid [border-radius value](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/border-radius#values) | `1rem` |
| `--media-color-primary` | The color of icons and text in media controls | [`<color>`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) | `red` |
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: is every skin going to support every CSS custom property? Maybe not now, but we should consider an api reference for each skin. (I know, eventually this will lead to a bloated sidebar, but, one problem at a time 😅 maybe eventually we'll add a gallery or something)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, can break it out into another page but I'll do that in a follow up PR if that's ok.

Comment on lines +144 to +147
#### Tailwind

- Currently we're assuming you're using the default configuration and that's all that's supported. With the release of our CLI, this will change, allowing you to specify a custom prefix to the Tailwind classnames. For now, you'll need to edit the ejected skins yourself.
- We're assuming the latest version, currently 4.2.x.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue(blocking):

you might've noticed that I haven't actually put the ejected tailwind skins in docs yet. Maybe now's the time we add them to customize-skins. I felt blocked by #840, but maybe I was letting perfect getting in the way of good enough.

We should either

  1. add the tailwind skins to the eject docs or
  2. remove this paragraph until we do add tailwind to the docs

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go with 2 for now.

Comment on lines +140 to +142
#### Vanilla CSS

- We use a [BEM](https://en.bem.info/methodology/quick-start/) classname structure and every component classname is scoped with a `media-` prefix.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question:

Is this relevant if our skins use shadow dom, unless you eject?
Or do our skins not use shadow dom?
Or do only our html skins use shadow dom? In which case, this info should be <FrameworkCase frameworks=["react"]> scoped.

I'm still so new to the html custom element world I'm not sure if my question makes sense. Lmk if I can clarify!

Copy link
Copy Markdown
Collaborator Author

@sampotts sampotts Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Non-ejected HTML skins don't need a stylesheet since it's in the Shadow DOM but ejected doesn't use the Shadow DOM but it reminds me we should document the stuff we're doing in SkinMixin since it injects a base.css file that sets some required styles. I'll look into that as part of #928 .

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: I'm feeling some tension about both concepts/skins and how-to/customize-skins existing.

I actually agree with your choices to put a high-level overview in the concept guide, and then to get into the mechanics in the how-to guide. I'm not actually tossing out any blocking change requests. But I do want to think this through because I fear that the line between the two guides isn't very clear. Like, I can imagine your CSS custom property table existing in either guide. I can even imagine the eject instructions existing in the concept guide, especially once they become a one-liner CLI command. So why did they get their own how-to guide?

What would this look like if we drew the lines in different places? We could...

  1. leave things as you have them in this PR. There's a tiny bit duplicate content, with the skins concept focusing more on the high-level and customize-skins focusing more on implementation
  2. break up customize-skins into more specific guides. Call this one how-to/eject-skins and put the CSS custom properties in skins/concepts or an API reference for each skin
  3. consolidate everything into concepts/skins

Let's have this conversation in person. But also, don't let this conversation be blocking. Just something we should clear out eventually. It's not a problem yet.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to do option 2 if that makes sense. I'll do it in a follow up PR.

@sampotts sampotts force-pushed the docs/skin-styling branch from 2d490cc to 3701f82 Compare March 20, 2026 02:51
@sampotts sampotts merged commit 3a129fa into main Mar 20, 2026
5 of 10 checks passed
@sampotts sampotts deleted the docs/skin-styling branch March 20, 2026 02:51
@decepulis decepulis mentioned this pull request Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Skins: Styling documentation

3 participants