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, we create speech bubbles by putting several pieces of background images together… Like it’s some sort of a jigsaw puzzle. But today, it is totally possible to create a speech bubble using pure CSS only – 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.
QUICK SLIDES
TABLE OF CONTENTS
DOWNLOAD & NOTES
Firstly, here is the download link to the example code as promised.
QUICK NOTES
If you spot a bug, feel free to comment below. I try to answer short 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.
EXAMPLE 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.
CSS SPEECH BUBBLE
All right, let us now get into the steps of creating a speech bubble using pure HTML and CSS.
STEP 1) SIMPLE SPEECH BOX
1A) THE HTML
<!-- (A) "SPEECH BOX" -->
<div class="speech">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
Aye, all we need to create a speech bubble is just a normal <div>
– We will add some CSS magic to it later.
1B) THE CSS
/* (A) SPEECH BOX */
.speech {
/* (A1) FONT */
font-family: arial, sans-serif;
font-size: 1.1em;
/* (A2) COLORS */
color: #fff;
background: #a53d38;
/* (A3) DIMENSIONS + POSITION */
position: relative;
padding: 20px;
border-radius: 10px;
max-width: 320px;
}
This first step shouldn’t be any trouble. We are just creating a “usual CSS box” by adding background color, padding, font size, font color, and more. The only part to take note is position: relative
, this is necessary for positioning the “tail” of the speech bubble later.
STEP 2) ADD SPEECH BUBBLE “TAIL”
2A) 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 the “speech callout triangle tail”. In ancient days, creating this “tail” will involve positioning a triangle image. But in modern CSS, we only need a few lines of code – Yes, we only added a bottom
CSS class here.
2B) THE CSS
/* (B) ADD SPEECH "CALLOUT TAIL" */
/* (B1) USE ::AFTER TO CREATE THE "TAIL" */
.speech::after {
/* (B1-1) ATTACH TRANSPARENT BORDERS */
content: "";
border: 20px solid transparent;
/* (B1-2) NECESSARY TO POSITION THE "TAIL" */
position: absolute;
}
/* (B2) BOTTOM "CALLOUT TAIL" */
.bottom.speech::after {
/* (B2-1) DOWN TRIANGLE */
border-top-color: #a53d38;
border-bottom: 0;
/* (B2-2) POSITION AT BOTTOM */
bottom: -20px; left: 50%;
margin-left: -20px;
}
This may look confusing at first, but the essential points here are:
- (B1-1 & B2-1) 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 works. - (B1-2 & B2-2) Remember that we set
position: relative
on.speech
earlier? Setting.speech::after { position: absolute; bottom: 0; left: 50% }
will now center the triangle below the box. - (B2-2) But the percentage position will be off by a little bit, we have to offset it with the same amount of border. Since it is
border: 20px
in this example, we offset it back withbottom: -20px; margin-left: -20px;
STEP 3) POSITION THE “TAIL”
3A) 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 responsive speech bubble, this is kind of an optional step. If you want to reposition the “tail”, we can easily play around with the CSS. Take note, we have only changed the CSS classes here – top left right
.
3B) THE CSS
/* (C) DIFFERENT TAIL POSITIONS */
/* (C1) TOP */
.top.speech::after {
/* (C1-1) UP TRIANGLE */
border-bottom-color: #a53d38;
border-top: 0;
/* (C1-2) POSITION AT TOP */
top: -20px; left: 50%;
margin-left: -20px;
}
/* (C2) LEFT */
.left.speech::after {
/* (C2-1) LEFT TRIANGLE */
border-right-color: #a53d38;
border-left: 0;
/* (C2-2) POSITION AT LEFT */
left: -20px; top: 50%;
margin-top: -20px;
}
/* (C3) RIGHT */
.right.speech::after {
/* (C3-1) RIGHT TRIANGLE */
border-left-color: #a53d38;
border-right: 0;
/* (C3-2) POSITION AT RIGHT */
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 accordingly.
HALF TRIANGLE & CIRCLE BUBBLE
If you are looking for more ways to style the speech bubble, this section will walk you through a few more ways to play with the CSS.
THE HALF TRIANGLE
<!-- (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%;
}
This is a small variant of the above speech bubbles, using the borders to create a half triangle instead.
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 {
/* (E2-1) FONT */
font-family: arial, sans-serif;
font-size: 1.1em;
color: #fff;
text-align: center;
/* (E2-2) DIMENSIONS + POSITION */
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;
}
- (E) The idea here is to use:
.circular
as the “main” speech bubble..circular::before
and.circular::after
as two smaller “thought bubbles”.
- (E1) A very simple CSS trick, we set
border-radius: 50%
to turn all of the “components” into circles and ovals. - (E2) Self-explanatory, the cosmetics for the “main” speech bubble.
- (E3) Finally, draw the two smaller “thought bubbles”, and position them using
position: 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
CSS BORDERS
<!-- (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;
}
For you guys who are wondering how the triangle appears from thin air – As you can see, the border
around HTML elements are “cut” at 45 degrees.
TRIANGLE FROM CSS 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;
}
So the true form of the “magic triangle” is simply taking one side of the border.
LINKS & REFERENCES
- Example On CodePen – Pure CSS Speech Bubble
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!
Great tutorial! Easy to follow and works great!