Custom CSS for Twitch chat - Creating alternating message colors in Streamlabs

Hey everyone! I’m trying to style my Twitch chat widget and running into some issues. I want to create alternating colors for chat messages but the usual CSS selectors aren’t working as expected.

Here’s my current CSS setup:

@import url(https://fonts.googleapis.com/css?family=Inter:600);

* {
    box-sizing: border-box;
}

html, body {
    height: 100%;
    overflow: hidden;
}

body {
    text-shadow: 0 0 1px #000, 0 0 2px #000;
    background: {background_color};
    font-family: 'Inter';
    font-weight: 600;
    font-size: {font_size};
    line-height: 1.4em;
    color: {text_color};
}

#chatLog>div {
    animation: slideInLeft .25s ease forwards, fadeOut 0.4s ease {message_hide_delay} forwards;
    -webkit-animation: slideInLeft .25s ease forwards, fadeOut 0.4s ease {message_hide_delay} forwards;
}

.separator {
    display: none;
}

#chatLog {
    display: table;
    position: absolute;
    bottom: 0;
    left: 0;
    padding: 0 8px 8px;
    width: 100%;
    table-layout: fixed;
}

#chatLog>div {
    display: table-row;
}

#chatLog>div.removed {
    visibility: hidden;
}

#chatLog .emoticon {
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
    padding: 0.3em 0.15em;
    position: relative;
}

#chatLog .text,#chatLog .info {
    vertical-align: top;
    display: table-cell;
    padding-bottom: 0.08em;
}

#chatLog .info {
    width: 40%;
    text-align: right;
    padding-right: 0.4em;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

#chatLog .text {
    word-wrap: break-word;
    width: 60%;
}

.userBadge {
    display: inline-block;
    margin-right: 0.15em;
    position: relative;
    height: 0.9em;
    vertical-align: middle;
    top: -0.08em;
}

.username {
    margin-left: 0.15em;
}

I’ve tried different approaches to get alternating colors working:

.username {
    margin-left: 0.15em;
    color: #e856d4;
}
.username:nth-child(odd) {
    margin-left: 0.15em;
    color: #6bf2ce;
}

This makes everything the same color instead of alternating. I also tried:

.chatUser {
    color: #6bf2ce;
}
.chatUser:nth-child(even) {
    color: #e856d4;
}

But the nth-child selector doesn’t seem to work properly in the chat environment. Has anyone successfully implemented alternating message colors in Streamlabs chat? What’s the correct way to target chat elements for this effect?

The problem is Streamlabs’ table-based layout for chat messages - it screws up nth-child selectors because of weird inheritance issues. I fought with this same bug for weeks on my overlay. Here’s what actually works: target the table-row containers and use CSS variables to push color values down to child elements. Set your alternating colors on #chatLog > div:nth-child(odd) and #chatLog > div:nth-child(even) using custom properties like --username-color, then grab those variables in your username styles with color: var(--username-color, #defaultcolor). The table structure actually helps once you work with it - keeps row order consistent even when messages fade. Just watch out for other username selectors later in your CSS that might override the color inheritance.

Your problem comes from how Streamlabs messes with chat messages - it constantly reorders and removes DOM elements, which breaks nth-child selectors. I ran into the same thing with my overlay.

The fix isn’t better CSS selectors. Try CSS counters instead. Add counter-reset: chat-counter; to your #chatLog container, then counter-increment: chat-counter; on each #chatLog > div. You can use counter(chat-counter) with calc functions to handle odd/even states without relying on DOM position.

Or hook into Streamlabs’ existing animation classes. Every message gets slideInLeft animation, so you can modify that keyframe to assign colors based on animation-delay timing. This survives message removal since it’s tied to the animation cycle, not DOM structure.

I’ve hit this same wall tons of times with chat integrations. The issue isn’t just CSS selectors - Streamlabs constantly adds and removes messages, breaking any static styling you try.

You need something that assigns colors dynamically as messages arrive, not CSS tricks that fall apart when the DOM shifts. I fixed this by intercepting chat messages before they reach the overlay and preprocessing them with alternating color classes (‘color-a’ or ‘color-b’), then sending it to your overlay. You get true alternating colors that stick even when messages vanish or get filtered.

I built this with Latenode since it handles Twitch API connections and DOM stuff without coding. Just set up conditional logic that flips between your two colors for each new message. Takes maybe 10 minutes and works with any chat overlay.

Way better than wrestling with CSS selectors that weren’t meant for dynamic content.

Had this exact problem last year with my chat overlay. The issue is nth-child selectors look at element position among siblings, but Streamlabs chat doesn’t structure username elements as direct siblings like you’d expect. Each message gets wrapped in its own container div, which messes up the nth-child counting. I fixed it by using nth-of-type on the actual message containers instead. Try targeting #chatLog>div:nth-child(odd) and #chatLog>div:nth-child(even) then apply color styles to username elements inside those containers. So #chatLog>div:nth-child(odd) .username { color: #e856d4; } and #chatLog>div:nth-child(even) .username { color: #6bf2ce; }. This works with Streamlabs’ actual DOM structure and should give you the alternating colors you want.

Yeah, this is a super common issue with Streamlabs CSS. I ran into the same thing. What fixed it for me was ditching nth-child selectors entirely - they break when messages appear and disappear dynamically. Instead, I used CSS custom properties with animation delays to fake the alternating effect. Try creating two animation classes and let Streamlabs assign them randomly. Or go with a time-based approach - modify the animation-delay property for color variations. Something like #chatLog>div { --color-shift: calc(var(--message-index) * 0.5s); } then reference that variable in your animations. Alternatively, use :nth-of-type() on the parent div containers instead of targeting username elements directly. The parent containers stay more consistent in Streamlabs’ DOM structure.

streamlabs injects messages async, so ur css selectors break when new chats roll in. i fixed this with javascript - just add a script that counts messages and toggles a class on each new one. something like document.addEventListener('DOMNodeInserted', function() { /* toggle color class */ }) works well enough for most overlays.