Skip to content

Creating custom designs

Redo edited this page Dec 29, 2025 · 11 revisions

Before you begin

You need to know HTML and CSS in order to make your own chat message / alert / osu! embed design

Field or Fields, represents the StreamElements widget settings or the fields JSON file, depending on the context. The current value of a field is kept in the Data tab of the StreamElements editor.

Setup

  1. Open the StreamElements editor
  2. Open the Fields tab
  3. Find the field responsible for switching the style of the element you want to edit
  • Those would be msgStyle, alertStyle, or embedStyle
  1. Inside of the options object, add a new unique entry with the value and label for your custom design

Finished edit should look more or less like this:

"embedStyle": {
    "group": "osu! integration",
    "type": "dropdown",
    "label": "Embed style:",
    "value": "osu-embed-a",
    "options": {
      "osu-embed-a": "Type A (osu!web)",
      "osu-embed-b": "Type B",
      "osu-embed-c": "Type C",
      "my-custom-embed": "Custom embed"
    }
  },

Remember the value you put in there for later. In this case it would be my-custom-embed.

HTML

Inside of the HTML tab, you will find a templates tag like this:

<templates class="hide">
    <!-- A lot of stuff will be here -->
</templates>

Create a new tag with the value you put in the fields JSON

<templates class="hide">
    <!-- A lot of stuff will be here -->
    <my-custom-design>
    </my-custom-design>
    <!-- or here -->
</templates>

Anything you put in-between those tags will render each time the appropriate event comes.

Add your own HTML and CSS as you see fit.

Important

Make sure to give your elements unique class names, so they don't overlap with ones already used by the widget (unless you want to reuse them, in which case it's fine)

Put this div as the direct child of your template.

<div data-sender="${uId}" data-msgId="${msgId}" id="msg-${totalMessages}" class="chat-message animate__animated ${animationIn}">
    <!-- All of your elements go in here -->
</div>

Important

Without it, things like deleting messages and message animations will not work.

You also shouldn't put any other direct children besides the one mentioned earlier inside your template. If you did, they would not be deleted properly when messages flow in.

✅ Good usage example:

<templates class="hide">
    <!-- A lot of stuff will be here -->
    <my-custom-design>
        <div data-sender="${uId}" data-msgId="${msgId}" id="msg-${totalMessages}" class="chat-message animate__animated ${animationIn}">
            <p>${username}</p>
            <p>${message}</p>
            <!-- All elements inside the only child of the template ✅ -->
        </div>
    </my-custom-design>
    <!-- or here -->
</templates>

❌ Bad usage example:

<templates class="hide">
    <!-- A lot of stuff will be here -->
    <my-custom-design>
        <p>${username}</p> <!-- Element inside the template, but outside the div ❌ -->
        <div data-sender="${uId}" data-msgId="${msgId}" id="msg-${totalMessages}" class="chat-message animate__animated ${animationIn}">
            <p>${message}</p>            
        </div>
    </my-custom-design>
    <!-- or here -->
</templates>

Variables

To use event data inside your template, you need to use the ${variableName} format, just like in this example:

<ranked-status class="${status}">${status}</ranked-status>

Here's a breakdown of what each one does:

Shared

These are used by all events

  • totalMessages - The # of the message since the widget was loaded
  • animationIn - The CSS class of the "in" animation set in fields. Requires animate__animated class to be present as well

Message

  • uId - ID of the user
  • msgId - ID of the message
  • message - The message content, including emotes rendered as <img /> tags
  • emoteOnly - A css class. emote-only if the message contains only emotes, an empty string otherwise
  • username - The sender's username
  • color - The sender's username color. Sourced from usernameColorSource in fields
  • avatar - The sender's avatar
  • badges - All badges
  • badgeStyle - A class to dictate whether badges are visible or not. Empty string if they are, hide if they're not
  • userRole - Role of the user. Either regular, subscriber, vip, moderator, or broadcaster
  • roleIcon - The icon associated with the user's role. Set in fields
  • roleIconStyle - A class to dictate whether the role icon is visible or not. Empty string if it is, hide if it's not
  • pronoun - The user's pronoun. null if unset
  • pronounStyle - A class to dictate whether the pronoun is visible or not. Empty string if it is, hide if it's not
  • replyTo - Username of the user being replied to
  • replyBody - The message the user is replying to
  • replyIcon - Arrow icon
  • replyStyle - A class to dictate whether the reply is visible or not. Empty string if it is, hide if it's not

Alerts

  • direction - Value of alertDirection. Either left, right, top, or bottom. Doesn't do anything on itself. Only used as a selector in CSS
  • alertText - Parsed event text from {event name}Text field for the current event

osu! Embeds

General
  • uId - ID of the user
  • msgId - ID of the message
  • username - The sender's username
  • userRole - Role of the user. Either regular, subscriber, vip, moderator, or broadcaster
  • roleIcon - The icon associated with the user's role. Set in fields
  • scroll - boolean - Should the text be scrolling? The true or false value is automatically assigned depending on the width of the child compared to the parent. Should be exclusively used as:
<overflow-text scroll="${scroll}">
    <p class="your-class">${variable}</p>
</overflow-text>
Fields
  • stat1Text / stat2Text / stat3Text / stat4Text - Value set in the corresponding field, which is then pulled from the API.
  • stat1Icon / stat2Icon / stat3Icon / stat4Icon - Icon associated with the value set in the corresponding stat#Text field
Direct beatmap data (osu!APIv2)
  • difficulty - Star Rating
  • status - Ranked status
  • total_length - Length of the song
  • diff_name - Difficulty name
  • accuracy - Overall Difficulty (not star rating!)
  • ar - Approach Rate
  • bpm - BPM (beats per minute) of the song
  • cs - Circle Size
  • hp - HP Drain
  • max_combo - Max achievable combo
  • artist - Song artist
  • title - Song title
  • thumbnail - Square cover image
  • background - Wide cover image
  • mapper - Beatmapset owner

Clone this wiki locally