EASY Custom Twitch Chat! Add Background Images & Animation to your Chat Overlay! 15-minute tutorial

Table of Contents

The overlay for Twitch chat has always been that generic black or transparent chat window with the colored user names. Have you ever wanted to play around with this by adding background images and animating the entrance and exit of the chat lines? This is a tutorial on using jChat on OBS. jChat is an awesome free Twitch chat overlay. This tutorial assumes that you have CSS knowledge or that you have at least gone through the previous tutorial: DIY Twitch Chat Overlay Tutorial for OBS. A video of this entire tutorial is available here:

The normal way to do this is to go to OBS, maybe add another browser source and customize the CSS straight away. But that’s very annoying since the chat overlay resets to blank everytime you press the “ok” button, so let’s make this easier with some preparations.

Add Custom Twitch Chat to OBS

Go to jChat, get your chat overlay link and paste it. Next, go to your Twitch chat through your Creator Dashboard or your Twitch channel; doesn’t matter as long as you can chat. On Windows, click on your Twitch chat browser window and press Win+Left, the left arrow key, to send it maximized to the left side and Win+Right on your jChat window. Sorry, I don’t know how to do this on Mac and Linux but you can resize your windows normally anyway.

Custom Twitch Chat for OBS

Next, on your jChat window, right-click on this blank slab of white and select “Inspect element”. Select the tag and click on this + sign to add a new rule for the body element. Set the background color to whatever you want to simulate since I doubt you’ll want to test this with a pure white background. As you might be aware, this fake “inspector-stylesheet” in the Sources tab of Chrome is temporary but will allow us to see our changes in real-time. At the end of your styling, all you have to do is copy all your CSS to the OBS browser source!

Be careful not to touch or override the original body selector of the browser source since this tells the browser source that the body should not have a white background and have a transparent one instead.

Back to Customization Basics

Let’s start from scratch. Let’s say you wanna put a background image for your entire chat overlay like a wallpaper. In your #chat_container selector, add a background-image property with the url: () value. Put the location of your image inside the parentheses and enclose it with single quotes. Don’t forget the semi-colon after.

#chat_container {
     ...
     background-image: url('your image URL here');
}

Once you’re done with the background-image property, add another one called background-repeat and set it to no-repeat. Backgrounds are set to repeat, or tile, by default. Take note to check if your background image has a transparent or opaque background especially if you have something like this. You may either want to remove the background and save it as a PNG, or get the color of your image and apply it to your container’s background, or find something else. Here’s something you can end up with:

To add a border, add a border property and set the style, width, and color. To make rounded corners, add a border-radius property. If you need to make adjustments, there are properties called background-size and background-origin. Here’s a reference from W3Schools.

#chat_container {
     background-image: url('your image URL here');
     background-repeat: no-repeat;
     background-color: rgba(0, 0, 0, 0.4);
     border: solid 2px black;
     border-radius: 15px;
}

Improving Readability

If you need to make things more readable, you can put a semi-transparent background on the .chat_line class or on the .user_info and .message classes individually. To apply it on the entire chat line because, let’s say, you have a design for each chat line like this, add a .chat_line selector, and add the background-image property into the .chat_line class.

.chat_line {
     ...
     background-image: url('your image URL here');
}

If you want to give some vertical space between the chat lines, add a margin-top as well. If you still want a border on your entire chat container with this, remove the padding to remove the space between the chat container’s border and the chat lines. The unit of measurement I used here is “rem”. 1rem means 100% of the font size of the root element – the html element. So if the font size of your html selector was 16px (like the default), the top margin of our .chat_line would also be 1rem. Setting this to 1.5rem would give us 24px.

.chat_line {
     ...
     margin-top: 1rem;
}
#chat_container {
     ...
     padding: 0;
}

I personally like separating the user info and the message into their own lines, so let’s do that. Create a selector for the .message class. Add a display: block property to the .message class to put it in its own line. Transfer the background image property from .chat_line to .message.

.message {
     ...
     display: block;
     background-image: url('your image URL here');
}

Before continuing, let’s remove the colon by creating a selector for the .colon class and adding a display: none property. I’m gonna remove the settings for the chat container: borders and backgrounds. Add background color, padding, and border radius in the .user_info class if you like. For padding, I’m gonna add 12px for top, 25px for right, 0 for bottom, 25px for left. For the border radius, 10px here and here, then 0 here.

Making Code Readable: Shorthand CSS

Again, remember that if you put only one number, it applies to all the sides or corners. If you put two, that’s vertical and horizontal for sides while it would mean top-left/bottom-right and top-right/bottom-left for corners. If you put four numbers, that would be top, right, bottom, left for sides, then top-left, top-right, bottom-right, bottom-left for corners. You can add padding and border radius on your .message class if you want to. Our code so far:

/* recap #1 */
body {
     background-color: (0,0,0,0.8);
}
#chat_container {
}
.chat_line {
     margin-top: 1rem;
}
.user_info {
     background-color: rgba(133, 7, 0, 0.6);
     padding: 12px 25px 0 25px;
     border-radius: 10px 10px 0 0;
}
.message {
     display: block;
     background-image: url('your image URL here');
     padding: 12px;
     border-radius: 0 10px 10px 10px;
}
.colon {
     display: none;
}

Move it: Animation!

Here comes the neat part: animation! Now, there are tons and tons of ways to do this so please feel free to share them in the comments or in my Discord! Please stay with me as this may get a little technical.

In this specific example, we’ll make the chat line slide in from the right. First, let’s add an animation property to the .chat_line class. I will put 3 values here: “schlacka-blacka”, “0.8s”, and “ease-in-out”. This is a shorthand declaration for 3 of the animation properties: name, duration, and timing function. You can separate them into their own properties like this: animation-name, animation-duration, and animation-timing-function respectively. I put a randomish name for the animation-name property just to let you know that you can use whatever you want; it’s not a keyword. The animation duration is in seconds but you can put decimals like I did. And lastly, the basic timing functions can be linear, ease, ease-in, ease-out, and ease-in-out.

.chat_line {
     ...
     animation: schlacka-blacka .8s ease-in-out;
}

If you want to learn more or learn all the possible values for each property, again you can visit w3schools.com. I’ve been using this site as a dictionary probably since 2003 or something. Or just go ahead and Google “css animation”.

Animation @keyframes

Next, to set the details of the animation, we’ll need to create @keyframes rules. Type in @keyframes then the name of the animation you used a while ago. Inside, create a from rule and a to rule. In the from rule, add a transform: translateX(400px) property. This will set the origin of the chat line 400 pixels to the right of the original position. You may have to adjust this number as needed in your OBS scene. In the to rule, add the same but set “translateX” to 0. Wooo yeah!

@keyframes schlacka-blacka {
     from {
          transform: translateX(400px);
     }
     to {
          transform: translateX(0);
     }
}

Now, let’s add a subtle fade in animation by adding opacity: 0 to the from rule and opacity: 1 to the to rule.

@keyframes schlacka-blacka {
     from {
          transform: translateX(400px);
          opacity: 0;
     }
     to {
          transform: translateX(0);
          opacity: 1;
     }
}

Sliding Entry Animation

Now, let’s add some subtle changes by sliding in the user’s name from the bottom then sliding their message from the right after some delay. I think this looks way cooler. That’s, of course, my opinion. Alright, alright… I’m just making excuses to subliminally inject some more CSS lessons. Add animation property to .user_info with the “user-entry” animation name, .8 seconds duration, and “ease-in-out” easing. Add the same animation property to .message. For now, nothing will happen because we haven’t defined what “user-entry” does, so let’s do that.

.user_info {
     background-color: rgba(133, 7, 0, 0.6);
     padding: 12px 25px 0 25px;
     border-radius: 10px 10px 0 0;
     animation: user-entry .8s ease-in-out;
}
.message {
     display: block;
     background-image: url('your image URL here');
     padding: 12px;
     border-radius: 0 10px 10px 10px;
     animation: user-entry .8s ease-in-out;
}

Add @keyframes user-entry. Add a from keyword and transform: translateY(40px), then add a to keyword and transform: translateY(0). The transform: translateY(40px) property in the from selector sets this element to start 40 pixels below its original position. Note the positive number. You can try using -40px to make it slide down instead. The transform: translateY(0) in the to selector then sets it back to its original position. Next, we’ll fade them in by adding opacity: 0 to the from selector and opacity: 1 to the to selector.

@keyframes user-entry {
     from {
          transform: translateY(40px);
          opacity: 0;
     }
     to {
          transform: translateY(0);
          opacity: 1;
     }
}

Controlling Animation Details

The “from” and “to” keywords are called keyframe selectors and these are just easier ways to specify start and end properties. Oh, you can actually replace them with percentages if you want more advanced animations! Maybe I’ll find another excuse to use them in another tutorial in the future; maybe in 15 years or something.

Go to the animation property of the .message class and add “.3s” (0.3 seconds) at the end. This is the animation-delay property. You can specify this separately like this if you wanted.

.message {
     ...
     animation: user-entry .8s ease-in-out .3s;
}

/* code above is shorthand for: */

.message {
     ...
     animation-name: user-entry;
     animation-duration: .8s;
     animation-timing-function: ease-in-out;
     animation-delay: .3s;
}

If you noticed, there’s this annoying effect where the message starts out visible then immediately blinks out before animating.

Let’s fix this by setting the initial opacity property of the message to 0. The new problem is that it goes back to 0 opacity after the animation. So let’s freeze the animation at the end by adding “forwards” at the end of the animation property of the message. This is the animation-fill-mode property which, again, you can specify separately since the shorthand values can get confusing.

.message {
     ...
     animation: user-entry .8s ease-in-out .3s forwards;
}

/* code above is shorthand for: */

.message {
     ...
     animation-name: user-entry;
     animation-duration: .8s;
     animation-timing-function: ease-in-out;
     animation-delay: .3s;
     animation-fill-mode: forwards;
}

Bring Everything Back to OBS

Now, copy all your CSS, then go to OBS, add a browser source or edit your existing one, double-click, paste your CSS and test out your chat! Alright!

If you lost the original properties of the body element, don’t worry. You can just make a new one, copy those CSS settings, and paste them at the top.

Aaaand because you stayed ’til the end, here’s some bonus fun stuff! Copy the user-entry keyframes rule and set this to message-entry. Change the transform property from “translateY” to “rotate(0)” and then “rotate(360deg)”. Please don’t forget the “deg” unit; rotation is always in degrees. Remove the opacity properties.

@keyframes user-entry {
     from {
          transform: translateY(40px);
          opacity: 0;
     }
     to {
          transform: translateY(0);
          opacity: 1;
     }
}
@keyframes message-entry {
     from {
          transform: rotate(0);
          opacity: 0;
     }
     to {
          transform: rotate(360deg);
          opacity: 1;
     }
}

Go to the .message class now and add the property animation-direction: infinite. Let’s remove its uh… wobbly bobbly thing by changing the animation-timing-function from “ease-in-out” to “linear”.

.message {
     ...
     animation: user-entry .8s linear .3s forwards;
     animation-direction: infinite;
}

/* code above is shorthand for: */

.message {
     ...
     animation-name: user-entry;
     animation-duration: .8s;
     animation-timing-function: linear;
     animation-delay: .3s;
     animation-fill-mode: forwards;
     animation-direction: infinite;
}

I hope you learned something from this tutorial! Please feel free to browse my other tutorials!


Discover more from The Sidestream Network

Subscribe to get the latest posts sent to your email.


honganqi Avatar

About the author


Search


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.