# Themes

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

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

A player template is comprised of a HTML and CSS definition of the player elements. To use a player template, 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` settings.

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.

### **Template Options**

The following additional options are available when configuring a playlist

| Value            | type    | Description                                      | Default |
| ---------------- | ------- | ------------------------------------------------ | ------- |
| htmlFile         | string  | URl of the template. 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 template       | true    |
| audioDescription | boolean | For hiding the description in the audio template | 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 Template (Video)**

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

    [[context]]

    <div data-role="channel-label"></div>
    <div data-role="title"></div>

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

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

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

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

    [[watermark]]

    <div data-role="gradiant"></div>
    <div data-role="gradiant-top"></div>

    [[qosmenu]]

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

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

    [[infobar]]

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

### **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 template, you can use the same fields as described [here](/player-web-sdk/labels.md). 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:

```javascript
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]]`)

```javascript
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**

```html
<div data-role="context">
  <ul data-role="context-ul">
    <li data-role="context-li">
      <b>3Q</b> Videoplayer v${__PLAYER_VERSION__}
    </li>
    <li data-role="context-li-third">{{stats}}</li>
  </ul>
</div>
```

The cog menu for quality- and language-settings.

#### **Markup**

```html
<div data-role="qos-menu">
  <h2 data-role="qos-menu-header">
    {{tips.settings}}
    <button
      tooltip-position="left"
      tooltip="{{tips.settingsClose}}"
      data-role="qos-menu-header-close-button"
    ></button>
  </h2>

  <div data-role="qos-menu-wrapper">
    <div data-role="qs-playbackrate-settings">
      <h3>{{playbackrate}}</h3>
      <ul data-role="qs-playbackrate-menu"></ul>
    </div>

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

    <div data-role="qs-audio-settings">
      <h3>{{audiotracks}}</h3>
      <ul data-role="qs-audio-menu"></ul>
    </div>

    <div data-role="qs-cc-settings"></div>
  </div>
</div>
```

### **\[\[seekbar]]**

The seekbar which indicates the progress of the content

#### **Markup**

```html
<div data-role="seek-bar">
  <div data-role="scrubberbar"></div>
  <div data-role="scrubber-loaded">
    <div data-role="scrubber-loaded-pointer"></div>
  </div>
  <div data-role="scrubberdragger"></div>
  <div data-role="scrubber-playahead"></div>
</div>
```

### **\[\[videoControls]]**

The control bar for video content

#### **Markup**

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

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

  <button data-role="timeleft-display">
    <span data-role="timeleft-span">
      ● Live
    </span>
  </div>

  <button
    data-role="enter-button"
    tooltip="{{tips.fullscreen}}"
  ></button>
  <button
    data-role="exit-button"
    tooltip="{{tips.exitfullscreen}}"
  ></button>
  <button data-role="qos-button" tooltip="{{tips.settings}}"></button>
  <button data-role="cast-button" tooltip="{{tips.cast}}"></button>
  <button
    data-role="airplay-button"
    tooltip="{{tips.airplay}}"
  ></button>
</div>
```

### **\[\[audioControls]]**

The control bar for audio content

#### **Markup**

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

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

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

  <button data-role="timeleft-display">
    <span data-role="timeleft-span">
      ● Live
    </span>
  </button>
</div>
```

### Minimal Example Audio Player <a href="#page_minimal_example_audio_player" id="page_minimal_example_audio_player"></a>

```html
<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>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://player.docs.3q.video/player-web-sdk/themes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
