Like me, you may have started watching more Twitch streams in the last two years. One of the things that makes a Twitch stream fun and interactive are the overlays that react to the chat's input. So by the end of this tutorial, you'll have a simple chat overlay to use in your streams. You can take this tutorial and build on it to make more complex and interactive overlays.
Prerequisites
If you are a beginner at web dev, this is for you. To complete this tutorial, you'll need to know some HTML, CSS, JS. We'll need ComfyJS to complete the project.
Project requirements:
- ComfyJS by Instafluff
Table of contents
- Setting up the project
- Connecting to Twitch chat
- Sending messages to the DOM
- Styling
- Adding animation
- Adding different styles based on roles
Setting up the project
We'll be writing our code in a single HTML file. Create a chat.html file and add the following:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Twitch chat</title>
</head>
<body>
<div id="chat">
<ul>
</ul>
</div>
</body>
</html>
We'll be putting our Twitch messages in the <ul>
block as <li>
elements. Next, let's integrate with Twitch.
Connecting to our Twitch chat
We'll be using ComfyJS to integrate with our Twitch chat. It's a very easy-to-use library, and it only takes a few lines of code to connect with our chat. Let's add this code to our <head>
:
<script src="https://cdn.jsdelivr.net/npm/comfy.js@latest/dist/comfy.min.js"></script>
Next, we need to add a <script>
tag below our <body>
tag and add the following:
ComfyJS.onChat = (user, message, flags, self, extra) => {
console.log(user, message);
}
ComfyJS.Init("YourTwitchName");
ComfyJS.Init()
lets us connect to our Twitch account, so remember to replace YourTwitchName with your channel name. We want to test if we're connected to our chat, and we can do that by going to our Twitch Creator Dashboard and selecting Stream Manager. There, you'll see a "My Chat" window where you can send messages to test your code. If you open chat.html in your browser and open your dev tools, you'll see the messages appear.
Sending messages to the DOM
So now that we're receiving messages from our chat let's start sending them to our DOM. We'll adjust our code in our <script>
to the following:
var chat = document.querySelector("#chat>ul");
ComfyJS.onChat = (user, message, flags, self, extra) => {
var newMessage = document.createElement("li");
newMessage.innerText = `${user}: ${message}`;
chat.append(newMessage);
}
ComfyJS.Init("YourTwitchName");
We're creating a new <li>
element for each message we receive and adding the user and message to it. That gets appended to our <ul>
block.
We want to separate the user from the message and give it some spacing for our purposes. So we'll change the code to the following:
var chat = document.querySelector("#chat>ul");
ComfyJS.onChat = (user, message, flags, self, extra) => {
var newMessage = document.createElement("li");
var text = document.createElement("blockquote");
newMessage.innerText = user;
text.innerText = message;
newMessage.append(text);
chat.append(newMessage);
}
Styling
Our chat is working, but we don't want to add it to our stream in this state😅. Let's add some CSS to make it look more impressive. Start by adding <style>
tags to our <head>
. To that, we're going to add these rules:
Fix the width and height of our chat
#chat {
width: 400px;
height: 350px;
}
You can set this to any width and height. Just remember what values you've chosen for later.
Style the messages
#chat li {
background-color: hsl(196, 58%, 93%);
box-sizing: border-box;
padding: 1rem 10px;
margin-bottom: 10px;
}
#chat ul {
list-style-type: none;
list-style-position: outside;
}
Note: We're using box-sizing: border-box;
here so that our padding and margins don't increase the width of our messages.
Set chat to auto overflow
#chat {
width: 400px;
height: 350px;
overflow-y: auto;
}
We're setting the overflow-y
property because we want to affect the vertical overflow of the chat. We set it to auto because we want the chat to start its scrolling behaviour when it starts to overflow.
Display the chat from the bottom up
#chat {
width: 400px;
height: 350px;
overflow-y: auto;
display: flex;
flex-direction: column-reverse;
}
We want the last message to appear in our chat and push our older messages up and off the screen. To do this we set our display
property to flex
and set the flex-direction
to column-reverse
.
Remove scrollbars
#chat::-webkit-scrollbar {
display: none;
}
At this point, our chat is starting to look decent. Below is the full stylesheet with additional rules to get our final result:
html,body {
margin: 0;
font-family: monospace;
color: hsl(197, 62%, 32%);
}
#chat {
width: 400px;
height: 350px;
overflow-y: auto;
display: flex;
flex-direction: column-reverse;
}
#chat::-webkit-scrollbar {
display: none;
}
#chat ul {
list-style-type: none;
list-style-position: outside;
}
#chat li {
background-color: hsl(196, 58%, 93%);
box-sizing: border-box;
padding: 1rem 10px;
margin-bottom: 10px;
border: 4px solid;
}
#chat blockquote {
font-size: 1.2rem;
}
Adding animation
To make our chat look even cooler, we're going to have each new message enter and slide in from the left. First, we want to define our @keyframes
animation:
@keyframes slide-in-left {
from {
transform: translateX(400px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
Next, we'll target our most recent message with last-of-type
and apply the animation to it:
#chat li:last-of-type {
animation-name: slide-in-left;
animation-duration: 0.15s;
animation-timing-function: ease-in;
}
These 2 CSS rules are enough to give us an entrance animation. You can try and make the top message animate off screen using li:nth-child()
as a bonus activity.
Finally, to make the newest message stand out, we'll make our older messages a bit transparent:
#chat li:not(:last-of-type) {
opacity: 0.5;
}
Here is the final result with the animation.
Conclusion
We've made a great looking chat overlay, and now you can show your audience what you've made on your streams. Here is a tutorial on how you can add your HTML file to OBS. It will run just like it did in our browser, but remember to set the width and the height to the same values we used for #chat
in our CSS. And here is a repo of this project on Github.
This was just a taste of what you can do with ComfyJS. It's a great library for making fun projects for your stream. Check out PixelPlush, TrostCodes, and whitep4nth3r for inspiration on overlay and interaction ideas. Thank you to LunchDevCommunity for their rudimentary chat overlay.
Lastly, I challenge you to extend this chat by setting different colours for your mods and subscribers (hint: you can use the flags mod
and subscriber
).
Thank you for reading my article. I'm new to writing, so any feedback on whether this was helpful or not, or topics you might be interested in are welcome.
See you at the next one!
Top comments (5)
Amazing article, it really helped out a lot. I'm really new in the frontend business (only a student) so I don't really have a deep understanding of JS yet. Could I perhaps ask you to tell me how I could display badges and emotes as well?
Hi Krisztián,
Thank you for your feedback! Right now, with ComfyJS (which is the library used to connect with the Twitch chat) you aren't able to get the actual images for badges and emotes. There is a an
extra
parameter that contains information like the emoteid
, but I haven't tried using it to reference an emote image. If someone else knows more, hopefully they can let us know.I just tried developing a twitch chat overlay and figured out how to parse the emote and badge through its id.
With emote it is easier as you can just use this function I found from a tmi development thread here
For badge, get this JSON file. There may be a cleaner simpler solution, but I just loop through the
extra.userBadges
parameter and compare and grab the image from the JSON file above. A rather brute force way.I hope I explain it well enough, I'm not really good with the technical web development term haha
These resources are great! Thanks for sharing.
No problem, it's quite difficult to come by documentation or solution for comfy.js. Is only by chance I found out that it used tmi library for twitch that I was able to find out how to parse emotes and badges as image. Hopefully this is another tip for some other features that future developers want to develop, try to look into tmi development too.