With our theme framework you can create your own custom player designs. This feature is available with player version v5.1 and above.

<script type="text/javascript">
var js3qVideoPlayer = new js3q({
    dataid: '5c3b0910-8850-11e7-9273-002590c750be',
    container: 'player',
    template: {
        htmlFile:"*httpPathToFile*",
        //html: `<div class="myCustomDiv"> ... </div>`,
        cssFile:"*httpPathToFile*",
        //css: `.myCustomDiv { color: red; ... }`,
    }
});
</script>

A player theme is comprised of a HTML and CSS definition of the player elements. To use a player theme, you can provide links to these files hosted on your sever using the parameters htmlFile and cssFile. If you choose to host the files yourself, please check your CORS setting.

Alternatively you can post the markup inline using the config parameters html and css.

Hint: If you use inline Markup, we recommend using string literals (`) instead of quotes ( ", '), to avoid issues with line breaks.

Finally, it is also possible to upload the files directly to a player using our GUI.

Theme Options

The following additional options are available when configuring a playlist

Value type Description Default
htmlFile string URl of the theme. Be aware of CORS
html string inline Markup
cssFile string URL of the CSS
css string inline CSS
audioPoster boolean For hiding the cover in the audio theme true
audioDescription boolean For hiding the description in the audio theme true

Syntax

You can add a class attribute to each container to define the CSS. The data-role attribute is used by our engine to map the button role. You can find a complete list of all buttons below.

Base Theme (Video)

<js3q-container data-role="sdn-player">
  <js3q-container data-role="sdn-display">
    <js3q-container data-role="sdn-stats"></js3q-container>
    <js3q-container data-role="motion-poster"></js3q-container>
    <js3q-container data-role="sdn-wall"></js3q-container>
    <js3q-container data-role="display-ad"></js3q-container>
    <js3q-button data-role="adskip-button"> {{skip}} </js3q-button>
    <js3q-button data-role="sdn-unmute-button"></js3q-button>

    [[context]]

    <js3q-container data-role="channel-label"></js3q-container>
    <js3q-container data-role="title"></js3q-container>

    <video
      data-role="source-container"
      x-webkit-airplay="allow"
      webkit-playsinline="true"
      playsinline="true"
      src=""
    ></video>

    <js3q-container data-role="play-button-overlay">
      <js3q-span data-role="play-button-overlay-span"></js3q-span>
    </js3q-container>

    <js3q-container data-role="play-buffer-overlay">
      <js3q-container data-role="play-buffer-overlay-spinner"></js3q-container>
    </js3q-container>

    <js3q-container data-role="player-controls">
      [[seekbar]] [[controls]]
      <js3q-container data-role="thumbnails"></js3q-container>
    </js3q-container>

    [[watermark]]

    <js3q-container data-role="gradiant"></js3q-container>
    <js3q-container data-role="gradiant-top"></js3q-container>

    [[qosmenu]]

    <js3q-container data-role="top-chrome">
      <js3q-container data-role="share-menu">
        <js3q-container data-role="sidebar-button"></js3q-container>
      </js3q-container>
    </js3q-container>

    <js3q-container data-role="sidebar"></js3q-container>

    [[infobar]]

    <js3q-container data-role="playlist"></js3q-container>
  </js3q-container>
</js3q-container>

Roles and Classes

data-role default css class required
sdn-player .js3q-player
sdn-audio-player .js3q-player.js3q-audio-player (as alternative to sdn-player)
sdn-display .sdn-display
sdn-stats .sdn-stats
motion-poster .sdn-motion-poster
display-ad .sdn-display-ad
adskip-button .sdn-display-adskipbutton
title .sdn-title
sdn-wall .sdn-wall
sdn-unmute-button .sdn-display-ad
context .sdn-context-menu
channel-label .sdn-channel-label
source-container .sdn-source-element
play-button-overlay .sdn-play-overlay
play-button-overlay-span .sdnicbsun-play.none-shadow
play-minus15-overlay .sdn-minus15-overlay
play-minus15-overlay-button .ssdnicbsun-minus15.none-shadow
play-plus15-overlay .sdn-plus15-overlay
play-plus15-overlay-button .ssdnicbsub-plus15.none-shadow
play-buffer-overlay .sdn-buffering
play-buffer-overlay-spinner .sdn-spinner
player-controls .sdn-player-controls
seek-bar .sdn-time-seekbar
scrubberbar .sdn-time-scrubber
scrubber-loaded .sdn-time-loaded
scrubber-loaded-pointer .sdn-time-loaded-pointer
scrubberdragger .sdn-time-playahead
scrubber-playahead .scrubbBarDragger
chrome .sdn-player-chrome
pause-button .sdn-button.sdn-play-button.sdnicbsun-play
play-button .sdn-button.sdn-play-button.sdnicbsun-pause
back-button .sdn-button.sdn-play-button.sdnicbsun-back
play-minus10-button .sdn-button.sdn-play-button.sdnicbsun-minus10
play-plus10-button .sdn-button.sdn-play-button.sdnicbsun-plus10
play-plus15-button .sdn-button.sdn-play-button.sdnicbsun-plus15
play-minus15-button .sdn-button.sdn-play-button.sdnicbsun-minus15
volume-button .sdn-button.sdnicbsun-volume3wave
volume-display-wrapper .sdn-volume-wrapper
volume-display .sdn-volume-slider
volume-controls-marker .sdn-volume-marker
volume-controls-thumb .sdn-volume-thumb
timeleft-display .sdn-button.sdn-time-left
timeleft-span
enter-button .sdn-button-right.sdnicbsun-fullscreen
exit-button .sdn-button-right.sdnicbsun-exitfullscreen
qos-button .sdn-button-right.sdn-audioonly-hidden.sdnicbsun-cog
cast-button .sdn-button-right.sdnicbsun-cast
airplay-button .sdn-button-right.sdnicbsun-airplay
thumbnails .sdn-thumbnails
gradient .sdn-player-gradiant
gradient-top .sdn-player-gradiant-top
qos-menu .sdn-qos-menu
qos-menu-header-close-button .sdn-button-right.sdnicbsun-close.sdn-hidden
qos-menu-wrapper .sdn-qos-menu-wrapper
qs-playbackrate-settings .sdn-quality-settings
qs-playbackrate-menu .sdn-ul-menu
qs-quality-settings .sdn-quality-settings
qs-audio-settings .sdn-audio-settings
qs-cc-settings .sdn-audio-settings
qs-audio-menu .sdn-ul-menu
top-chrome .sdn-top-chrome
share-menu .sdn-share-menu
sidebar-button .sdn-button-right.sdnicbsun-info.sdn-hide
playlist .sdn-playlist
infobar .sdn-infobar.sdn-hide
sidebar .sdn-sidebar
watermark .sdn-watermark
watermark-picture .sdn-watermark-picture

Labels/Language Strings

For language strings in the theme, you can use the same fields as described here. To embed them, place the field name between curly brackets. (e.g. {{tips.play}})

Not only you can use the built-in language strings, you can also define your very own ones:

const player = new js3q({
  //...
  labels: {
    de: {
      'my-special-language-string': 'Lorem Ipsum',
    },
    en: {
      'my-special-language-string': 'dolor sit amet',
    },
  },
  template: {
    html: `<div>
      {{my-special-language-string}}

      <div data-role="title"></div>
      <!-- ... -->
    </div>`,
  },
})

Components

Several components are separated for easier maintenance. You can override each component as described above, or you can create your own components.

To embed a component, place it between square brackets. (e.g. [[context]])

new js3q({
  //...
  template: {
    //...
    components: {
      audioPoster: {
        html: `<div class="outer" style="padding: 20px; background: lime;">
                <div class="inner">
                  <div data-role="audio-poster"></div>
                </div>
              </div>`,
        css: `
        .outer {
          /* Beware, that it is not possible to style the root element here */
          /* You need to style it inline, as shown above */
        }

        .inner {
          background: yellow;
          padding: 20px;
        }

        .sdn-ellipsis {
          display: none !important; // Does not affect the rest of the player, just works for the component
        }
      `,
      },
    },
  },
})
[[context]]

The right-click menu

Markup
<js3q-container data-role="context">
  <js3q-ul data-role="context-ul">
    <js3q-li data-role="context-li">
      <b>3Q</b> Videoplayer v${__PLAYER_VERSION__}
    </js3q-li>
    <js3q-li data-role="context-li-third"> {{stats}} </js3q-li>
  </js3q-ul>
</js3q-container>
[[qosmenu]]

The cog menu for quality- and language-settings.

Markup
<js3q-container data-role="qos-menu">
  <js3q-h1 data-role="qos-menu-header">
    {{tips.settings}}
    <button
      tooltip-position="left"
      tooltip="{{tips.settingsClose}}"
      data-role="qos-menu-header-close-button"
    ></button>
  </js3q-h1>

  <js3q-container data-role="qos-menu-wrapper">
    <js3q-container data-role="qs-playbackrate-settings">
      <js3q-h2>{{playbackrate}}</js3q-h2>
      <js3q-ul data-role="qs-playbackrate-menu"></js3q-ul>
    </js3q-container>

    <js3q-container data-role="qs-quality-settings">
      <js3q-h2>{{quality}}</js3q-h2>
      <js3q-ul class="sdn-ul-menu">
        <js3q-li>
          <js3q-span class="current">{{auto}}</js3q-span>
        </js3q-li>
      </js3q-ul>
    </js3q-container>

    <js3q-container data-role="qs-audio-settings">
      <js3q-h2>{{audiotracks}}</js3q-h2>
      <js3q-ul data-role="qs-audio-menu"></js3q-ul>
    </js3q-container>

    <js3q-container data-role="qs-cc-settings"></js3q-container>
  </js3q-container>
</js3q-container>
[[seekbar]]

The seekbar which indicates the progress of the content

Markup
<js3q-container data-role="seek-bar">
  <js3q-container data-role="scrubberbar"></js3q-container>
  <js3q-container data-role="scrubber-loaded">
    <js3q-container data-role="scrubber-loaded-pointer"></js3q-container>
  </js3q-container>
  <js3q-container data-role="scrubberdragger"></js3q-container>
  <js3q-container data-role="scrubber-playahead"></js3q-container>
</js3q-container>
[[videoControls]]

The control bar for video content

Markup
<js3q-container data-role="chrome">
  <js3q-button
    data-role="pause-button"
    tooltip="{{tips.play}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button
    data-role="play-button"
    tooltip="{{tips.pause}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button
    data-role="back-button"
    tooltip="{{playlist.playback}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button
    data-role="next-button"
    tooltip="{{playlist.playnext}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button data-role="play-minus10-button"></js3q-button>
  <js3q-button data-role="play-plus10-button"></js3q-button>
  <js3q-button data-role="play-minus15-button"></js3q-button>
  <js3q-button data-role="play-plus15-button"></js3q-button>
  <js3q-button
    data-role="volume-button"
    tooltip="{{tips.mutevolume}}"
    tooltip-position="left"
  ></js3q-button>

  <js3q-container data-role="volume-display-wrapper">
    <js3q-container data-role="volume-display">
      <js3q-container data-role="volume-controls-marker">
        <js3q-span data-role="volume-controls-thumb"></js3q-span>
      </js3q-container>
    </js3q-container>
  </js3q-container>

  <js3q-button data-role="timeleft-display">
    <js3q-container data-role="timeleft-span">
      <js3q-container></js3q-container> Live
    </js3q-container>
  </js3q-button>

  <js3q-button
    data-role="enter-button"
    tooltip="{{tips.fullscreen}}"
  ></js3q-button>
  <js3q-button
    data-role="exit-button"
    tooltip="{{tips.exitfullscreen}}"
  ></js3q-button>
  <js3q-button data-role="qos-button" tooltip="{{tips.settings}}"></js3q-button>
  <js3q-button data-role="cast-button" tooltip="{{tips.cast}}"></js3q-button>
  <js3q-button
    data-role="airplay-button"
    tooltip="{{tips.airplay}}"
  ></js3q-button>
</js3q-container>
[[audioControls]]

The control bar for audio content

Markup
<js3q-container data-role="chrome">
  <js3q-button
    data-role="pause-button"
    tooltip="{{tips.play}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button
    data-role="play-button"
    tooltip="{{tips.pause}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button
    data-role="back-button"
    tooltip="{{playlist.playback}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button
    data-role="next-button"
    tooltip="{{playlist.playnext}}"
    tooltip-position="left"
  ></js3q-button>
  <js3q-button data-role="play-minus10-button"></js3q-button>
  <js3q-button data-role="play-plus10-button"></js3q-button>
  <js3q-button data-role="play-minus15-button"></js3q-button>
  <js3q-button data-role="play-plus15-button"></js3q-button>
  <js3q-button
    data-role="volume-button"
    tooltip="{{tips.mutevolume}}"
    tooltip-position="left"
  ></js3q-button>

  <js3q-container data-role="volume-display-wrapper">
    <js3q-container data-role="volume-display">
      <js3q-container data-role="volume-controls-marker">
        <js3q-span data-role="volume-controls-thumb"></js3q-span>
      </js3q-container>
    </js3q-container>
  </js3q-container>

  <js3q-button data-role="qos-button" tooltip="{{tips.settings}}"></js3q-button>
  <js3q-button data-role="cast-button" tooltip="{{tips.cast}}"></js3q-button>
  <js3q-button
    data-role="airplay-button"
    tooltip="{{tips.airplay}}"
  ></js3q-button>

  <js3q-button data-role="timeleft-display">
    <js3q-container data-role="timeleft-span">
      <js3q-container></js3q-container> Live
    </js3q-container>
  </js3q-button>
</js3q-container>

Minimal Example Audio Player

<div data-role="sdn-audio-player">
  <div data-role="sdn-display" class="sdn-display sdn-display-audio">
    <div data-role="channel-label"></div>
    <div data-role="title"></div>

    <video data-role="source-container" class="sdn-source-element sdn-hidden" x-webkit-airplay="allow" webkit-playsinline="true" playsinline="true" src="">

    <div data-role="player-controls">
      [[audioControls]]
    </div>

    <div data-role="playlist"></div>
  </div>
</div>