Table of Contents
- Add Custom Twitch Chat to OBS
- Back to Customization Basics
- Improving Readability
- Making Code Readable: Shorthand CSS
- Move it: Animation!
- Animation @keyframes
- Sliding Entry Animation
- Controlling Animation Details
- Bring Everything Back to OBS
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.
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!
Leave a Reply