The New Video.js Themes

The ability to easily theme Video.js via a little CSS is one of the project's super powers. Sure, it can play back all the formats you need right out of the box and is easily extended via plugins, but a sprinkle of CSS allows you to quickly customize the very first thing a viewer sees.

When we sat down to redesign Videojs.com, we really wanted to highlight how easy it is to customize and extend, so we ended up building four new themes. This was both to give developers more style options out of the box and give a few examples of how to build your own. We built them in the way we'd suggest people build their own: by extending the base CSS.

Let's take a look at the default/base theme, which has not changed, to be clear.

Default Themes

And here we have the four new themes:

New Themes

Using the Themes in Your Project

An important thing to remember is that these themes are intended to be overrides for the base theme, which means you always need to pull in the base CSS first.

If you want to use <link> tags in your HTML, we suggest using unpkg.

<!-- Video.js base CSS -->
<link href="https://unpkg.com/video.js@7/dist/video-js.min.css" rel="stylesheet">

<!-- City -->
<link href="https://unpkg.com/@videojs/themes@1/dist/city/index.css" rel="stylesheet">

<!-- Fantasy -->
<link href="https://unpkg.com/@videojs/themes@1/dist/fantasy/index.css" rel="stylesheet">

<!-- Forest -->
<link href="https://unpkg.com/@videojs/themes@1/dist/forest/index.css" rel="stylesheet">

<!-- Sea -->
<link href="https://unpkg.com/@videojs/themes@1/dist/sea/index.css" rel="stylesheet">

Or, if you're using your CSS directly in JavaScript, you can install the NPM module and import them as you would your other CSS dependencies.

$ npm install --save video.js @videojs/themes

// awesome-player.js
// Base Video.js theme
import 'video.js/dist/video-js.css';

// City
import '@videojs/themes/dist/city/index.css';

// Fantasy
import '@videojs/themes/dist/fantasy/index.css';

// Forest
import '@videojs/themes/dist/forest/index.css';

// Sea
import '@videojs/themes/dist/sea/index.css';

Once you've got the theme pulled in, you can then add the relevant class to your player! The class names are structured as vjs-theme-${THEME_NAME}, so vjs-theme-city for the city theme or vjs-theme-sea for the sea theme.

<video id="my-player" class="video-js vjs-theme-city" ...>

Why not Sass?

When we rebuilt the default theme a few years ago we decided to switch over to Sass. It allowed us to break up our massive CSS file into components that matched the rest of the project and gave us features like variables, nesting, etc.

Sass is amazing, but it's another layer of technology to know. Sure, dependencies are installed, it will Just Work™ locally...but even someone that knows CSS will need to take a second to understand how Sass mixins and nesting work. We wanted these themes to be as accessible to as wide of an audience as possible, so we tried to keep the code itself as "vanilla" as we could.

Enter PostCSS. If Sass is CoffeeScript for CSS then PostCSS is more like Babel. If you're not familiar with either of those two things, the gist is that Sass has its own syntax that gets transformed into CSS, while PostCSS is intended to be standard, modern CSS that automatically gets things like vendor prefixes and polyfills applied.

PostCSS also has a very active ecosystem of plugins and processors built around it. This sometimes flies in the face of the "it's just CSS" claim, to be fair, and we absolutely want to be cautious about how many non-standard CSS extensions we bring in. However, one plugin that we thought was worth the tradeoff was postcss-inline-svg.

This allows us to inline SVGs we want to use in our themes right in the CSS at build, meaning that if you want to copy and paste a theme's CSS output into your own code, it will just work! No digging up other files on the CDN that you need to save somewhere on your server, etc. We wanted to try and keep these themes as self-contained as possible to maximize their portability.

Contributing New Themes

One of the things that has felt lacking over the years has been the ease of distributing and finding new themes. We tried doing it via a list in the Video.js Github wiki and later NPM tags, but both options felt like they had their own quirky barriers to discovery and maintainability.

So, if you check out the Github project, you'll see we decided to go with more of a monorepo approach. I've always loved the feeling of digging through Oh My ZSH themes and trying them all out before making a choice. That discoverability and ability to easily experiment with different themes isn’t something we’ve had before (unless you count some alternative themes Heff made for Video.js 1.0), so hopefully this changes that!

If you're interested in creating a theme, submit a PR! The project is still young, so if you have other ideas for how we can improve things on this front, please reach out.

Why did we do this?

Video.js is near and dear to the Mux founding team’s hearts for multiple reasons. The first, and probably most obvious one being because Heff created it in the early days of Zencoder. If you’re interested in the backstory, I highly suggest checking out the episode of the Demuxed podcast where we chat with the current Video.js lead maintainers, Gary Katsevman and David LaPalomento.

Personally, to some extent I owe my career to Video.js. Video.js was one of the main reasons I met the Zencoder team, which I ultimately joined. I started helping out with issues, and eventually became a core contributor to the project. It was my first experience with a large open source project and also helped make me feel like I really belonged in the video community.

These themes (and the new website!) are the first major contributions/investments we’ve been able to make back to the project in years, and especially given I’m the one to blame for the previous website, I couldn’t be more thrilled to be sharing it with you all.

✌️ @matt_mcclure