Welcome to a step-by-step tutorial on how to create simple responsive CSS speech bubbles. Once upon a time in the Stone Age of the Internet, CSS is not as convenient, and we have to create speech bubbles by placing several pieces of background images. Today, it is totally possible to create a speech bubble using only pure CSS – Read on to find out how.
ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.
REAL QUICK SLIDES
TABLE OF CONTENTS
DOWNLOAD & NOTES
Firstly, here is the download link to the example code as promised.
SOURCE CODE DOWNLOAD
Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
QUICK NOTES
If you spot a bug, please feel free to comment below. I try to answer questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.
CSS SPEECH BUBBLE
All right – Let us start now get into the steps of creating a speech bubble using pure CSS.
STEP 1) SIMPLE SPEECH BOX
THE HTML
<!-- (A) "SPEECH BOX" -->
<div class="speech">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
Aye, and all we need to create a speech bubble is just a normal <div>
– We will add some CSS magic to it later.
THE CSS
/* (A) SPEECH BOX */
.speech {
/* (A1) FONT */
font-family: arial, sans-serif;
font-size: 1.1em;
color: #fff;
/* (A2) DIMENSIONS + BACKGROUND */
position: relative;
background: #a53d38;
padding: 20px;
border-radius: 10px;
max-width: 320px;
}
Well, the first step shouldn’t be any trouble. Just to create a “usual CSS box” by adding background color, padding, font size, font color, and more. Take extra note that the position: relative
is necessary for positioning the “tail” of the speech bubble later.
STEP 2) ADD SPEECH BUBBLE “TAIL”
THE HTML
<!-- (B) SPEECH BUBBLE WITH BOTTOM TAIL -->
<div class="speech bottom">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
We now have a speech box, but it is missing that “speech callout triangle tail” part. Adding this tail used to involve a triangle image, but all we need now is a few lines of CSS code – Yes, we only added a bottom
CSS class here.
THE CSS
/* (B) ADD SPEECH "CALLOUT TAIL" */
/* (B1) ATTACH TRANSPARENT BORDERS AFTER */
.speech::after {
position: absolute;
content: '';
border: 20px solid transparent;
}
/* (B2) CREATE + POSITION CALLOUT "TAIL" */
.bottom.speech::after {
/* DOWN TRIANGLE */
border-top-color: #a53d38;
border-bottom: 0;
/* POSITION TAIL AT BOTTOM OF BOX */
bottom: -20px;
left: 50%;
margin-left: -20px;
}
This may look pretty confusing at first, but just a few essential things here:
- We create the “magic triangle” by playing with the
border
of the.speech::after
pseudo-class. Read the extras section below if you want to know how this triangle came about. - Remember that we set
position: relative
on.speech
earlier? Setting.speech::after { position: absolute; bottom: 0; left: 50% }
will now position the triangle centered below the box. - But the percentage position will be off a little, and we have to offset it with the same amount of border; Since it is
border: 20px
, we offset it back withbottom: -20px; margin-left: -20px;
That’s all. Feel free to play around with the left
percentage to shift the position of the tail.
STEP 3) POSITION THE “TAIL”
THE HTML
<!-- (C) POSITION TAIL -->
<div class="speech top">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div class="speech left">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
<div class="speech right">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
We already have a complete speech bubble that is responsive, and this is actually kind of an optional step. If you want to have the “tail” face a different direction, we can easily play around with the CSS – Take note, we have only changed the CSS class here top left right
.
THE CSS
/* (C) DIFFERENT TAIL POSITIONS */
/* (C1) TOP */
.top.speech::after {
/* UP TRIANGLE */
border-bottom-color: #a53d38;
border-top: 0;
/* POSITION TAIL AT BOTTOM OF BOX */
top: -20px;
left: 50%;
margin-left: -20px;
}
/* (C2) LEFT */
.left.speech::after {
/* LEFT TRIANGLE */
border-right-color: #a53d38;
border-left: 0;
/* POSITION TAIL AT LEFT OF BOX */
left: -20px;
top: 50%;
margin-top: -20px;
}
/* (C3) RIGHT */
.right.speech::after {
/* RIGHT TRIANGLE */
border-left-color: #a53d38;
border-right: 0;
/* POSITION TAIL AT RIGHT OF BOX */
right: -20px;
top: 50%;
margin-top: -20px;
}
Yep, this probably isn’t too difficult to understand now – All we did is just reposition the triangle differently.
HALF TRIANGLE & CIRCLE BUBBLE
Looking for more ways to style the speech bubble this alternative section will show you a few more ways to play with the CSS.
THE HALF TRIANGLE
This is a small variant of the above speech bubbles… Which we just play around with the borders to create a half triangle instead.
<!-- (D) HALF TRIANGLE TAIL -->
<div class="speech half">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
/* (D) HALF TRIANGLE TAIL */
.half.speech::after {
border-right-color: #a53d38;
bottom: -20px;
left: 80%;
}
CIRCULAR BUBBLE
<!-- (E) CIRCULAR BUBBLE -->
<div class="circular">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
/* (E) CIRCULAR SPEECH BUBBLE */
/* (E1) COMMON COLOR + MAKE ROUND */
.circular, .circular::before, .circular::after {
background: #a53d38;
border-radius: 50%;
}
/* (E2) "MAIN BUBBLE" */
.circular {
/* FONT */
font-family: arial, sans-serif;
font-size: 1.1em;
color: #fff;
text-align: center;
/* DIMENSIONS + BACKGROUND */
padding: 30px 30px;
max-width: 300px;
position: relative;
}
/* (E3) POSITION "CALLOUT" BUBBLES */
.circular::before, .circular::after {
content: '';
position: absolute;
}
.circular::before {
width: 20px;
padding: 20px;
right: 10px;
bottom: -30px;
}
.circular::after {
width: 10px;
padding: 10px;
right: 0;
bottom: -50px;
}
Circular bubbles are a tad bit more tricky but use the same positioning trick.
- The
.circular
container is the “main” speech bubble, and we use.circular::before
and.circular::after
as the two smaller “tails”. - The styles for
.circular
is pretty much the same as the above rectangular box, except that we give it aborder-radius: 50%
to turn it into a circle. - Instead of the “triangle tail”, we use the same
border-radius: 50%
trick on.circular::before
and.circular::after
to turn them into circles, then position them usingposition: absolute
.
That’s it! The circular bubble should be responsive as well, but do your own testing to see if it will break on the smaller screens.
USEFUL BITS
We are now done with the CSS speech bubble, here is a small extra section that may be useful.
EXTRA – THE MAGIC TRIANGLE
For you guys who are wondering – How did that triangle appear from thin air!? Let us start with setting all 4 borders with a different color.
<!-- (A) ALL BORDERS -->
<div class="borders"></div>
/* (A) BORDERS CUT AT 45 DEGREES */
.borders {
width: 0;
border: 20px solid;
border-top-color: black;
border-bottom-color: red;
border-left-color: green;
border-right-color: blue;
}
As you can see, the border
around HTML elements are “cut” at 45 degrees. So the true form of the “magic triangle” is simply taking one side of the border.
<!-- (B) CSS TRIANGLE -->
<div class="triangle"></div>
/* (B) KEEP ONLY ONE SIDE TO CREATE CSS TRIANGLE */
.triangle {
width: 0;
border: 20px solid transparent;
border-top-color: lightseagreen;
}
Yep. Not much of a mystery now. But a neat trick nonetheless.
YOUTUBE TUTORIAL
INFOGRAPHIC CHEAT SHEET

THE END
Thank you for reading, and we have come to the end of this short tutorial. I hope that it has helped you to build a better project, and if you have anything to add to this project, please feel free to comment below. Good luck and happy coding!