1. Core Concepts
  2. Tailwind

Core Concepts

Tailwind CSS

In this section, we'll get you up and running with our Tailwind CSS plugin.


If you're a fan of Tailwind CSS like we are, then you really don't want to be forced to create a .css file to handle random outlier cases. It not only slows you down and breaks your flow, but it also goes against all the advantages of using utility classes.


You will need to add the following VSCode setting to ensure Tailwind intellisense works with custom classes on components:

  "tailwindCSS.experimental.classRegex": ["[cC]lass=['\"](.*)['|\"]"]



You can register the plugin by adding the following to tailwind.config.js:

        module.exports = {
  plugins: [require('vidstack/tailwind.cjs')],



The plugin accepts options for configuring prefixes on variants provided by Vidstack:

        module.exports = {
  plugins: [
      prefix: 'media', // paused:... -> media-paused:...



The <media-player> element exposes media state as HTML data attributes vars like so:

        <media-player data-paused data-waiting data-seeking data-can-play ...>
  <!-- ... -->


The tailwind plugin provides media variants which can be used to prefix utilities so they're applied when a given media state is active.


Media Variants

        <!-- example -->
<div class="paused:opacity-0"></div>

autoplay-errorAutoplay has failed to start.
autoplayAutoplay has successfully started.
bufferingMedia is not ready for playback or waiting for more data.
can-controlMedia is ready for playback and user is not idle.
can-fullscreenMedia fullscreen is available.
can-loadMedia can begin loading.
can-pipPicture-in-Picture is available.
can-playMedia is ready to be played.
can-seekWhether seeking is permitted for live stream.
captionsCaption or subtitle text track is showing.
endedPlayback has reached the end.
errorIssue with media loading/playback.
fullscreenMedia is in fullscreen mode.
live-edgeCurrent time is at the live edge.
liveMedia is a live stream.
loopMedia is set to loop back to start on end.
mutedMedia is muted.
pausedPlayback is in a paused state.
pipMedia is in picture-in-picture mode.
playingPlayback has started or resumed.
playsinlineMedia should play inline by default (iOS Safari).
seekingMedia or user is seeking to new playback position.
startedMedia playback has started.
user-idleUser is not active during playback.
waitingMedia is waiting for more data (i.e., buffering).

Not Variants

All media variants can be prefixed with not- to negate the selector. Classes with this prefix will be transformed into media-player:not([state]) selectors.

Few examples:

  • not-paused: Media is in the play state (not paused).
  • not-playing: Media playback is not active (not playing).
  • not-can-play: Media is not ready for playback (not can play).
        <!-- input -->
<div class="not-paused:opacity-0"></div>

        /* output */
media-player:not([data-paused]) .not-paused\:opacity-0 {
  opacity: 0;


Data Attributes

Data attributes are applied to components throughout the library to expose internal state for styling purposes:

        <media-play-button data-paused />
<media-mute-button data-volume="high" />
<media-live-indicator data-live-edge />


Tailwind supports data attributes out of the box to apply styles conditionally like so:

        <media-mute-button class="group">
  <media-icon class="hidden group-data-[volume=muted]:block" type="mute"></media-icon>
  <media-icon class="hidden group-data-[volume=low]:block" type="volume-low"></media-icon>
  <media-icon class="hidden group-data-[volume=high]:block" type="volume-high"></media-icon>


👉 See the "Styling" and "Tailwind" sections for each component to see what data attributes are available for styling.


The focus-visible pseudo-class and Tailwind variant does not work with custom elements in Safari. To remedy this, a data-focus attribute is applied to components when focused via keyboard. This attribute can be used to apply focus styling in Tailwind like so:

        <media-play-button class="outline-none data-[focus]:ring-4 data-[focus]:ring-blue-400" />



The data-hocus attribute is applied to components when they're being keyboard focused or hovered on by a pointer device. This attribute is applied to help keep class lists concise and can be used like so:

        <media-play-button class="data-[hocus]:ring-blue-400" />


Previous <- Skins