497-css3-speech-bubbles

How to Create CSS3 Speech Bubbles Without Images

By | | JavaScript

I remember my creating my first image-less speech bubble many years ago. It required a long-winded JavaScript function to inject elements into the DOM, some horrendous CSS, looked fairly awful, and didn’t work well in IE5.

CSS3 is starting to change our lives for the better. It’s now possible to create a great looking speech bubble which works in all browsers, uses a single HTML element, a few lines of CSS3 code, no images, and no JavaScript whatsoever…

CSS3 speech bubble

To ease you in gently, let’s examine the HTML. A single element is required, so I’m using a P tag:


<p class="speech">SitePoint Rocks!</p>

First, we’ll style the outer box:


p.speech
{
	position: relative;
	width: 200px;
	height: 100px;
	text-align: center;
	line-height: 100px;
	background-color: #fff;
	border: 8px solid #666;
	-webkit-border-radius: 30px;
	-moz-border-radius: 30px;
	border-radius: 30px;
	-webkit-box-shadow: 2px 2px 4px #888;
	-moz-box-shadow: 2px 2px 4px #888;
	box-shadow: 2px 2px 4px #888;
}

Nothing too complicated there. The only essential property is position: relative which is necessary for the speech bubble pointer. We also require Mozilla and Webkit vendor prefixes for border-radius and box-shadow to ensure they work in all CSS3 browsers. IE8 and below will show squared corners and no shadow, but the box will still be visible.

CSS3 speech bubble

Now we need to create the triangular bubble pointer. Rather than resorting to images, we can use CSS borders to create any type of triangle. As a brief explanation, examine an element with wide differently-colored borders:

CSS3 border triangles

If we reduce the width and height of our element to 0px and use different sized borders, we can see different triangles being formed:

CSS3 border triangles

For our speech bubble pointer, we can therefore use a solid top and left border with transparent right and bottom borders:

CSS3 border triangles

But what do we assign those border properties to? Fortunately, we can use the CSS :before and :after pseudo-elements to generate two more content items. Therefore:


p.speech:before
{
	content: ' ';
	position: absolute;
	width: 0;
	height: 0;
	left: 30px;
	top: 100px;
	border: 25px solid;
	border-color: #666 transparent transparent #666;
}

The triangle is positioned at the bottom of our bubble. Incidentally, don’t bother trying to apply a shadow to this element — it’ll be shown around the transparent borders rather than the visible triangle.

CSS3 speech bubble

We must now remove a section of this triangle. We can position a smaller white triangle over the gray one to achieve that effect:


p.speech:after
{
	content: ' ';
	position: absolute;
	width: 0;
	height: 0;
	left: 38px;
	top: 100px;
	border: 15px solid;
	border-color: #fff transparent transparent #fff;
}

Our pure CSS3 image-less speech bubble is complete.

CSS3 speech bubble

In essence, we can utilize the :before and :after pseudo-elements to create many different effects. For example, a thought bubble can be created with two content items rounded into circles:


p.thought
{
	position: relative;
	width: 130px;
	height: 100px;
	text-align: center;
	line-height: 100px;
	background-color: #fff;
	border: 8px solid #666;
	-webkit-border-radius: 58px;
	-moz-border-radius: 58px;
	border-radius: 58px;
	-webkit-box-shadow: 2px 2px 4px #888;
	-moz-box-shadow: 2px 2px 4px #888;
	box-shadow: 2px 2px 4px #888;
}
p.thought:before, p.thought:after
{
	left: 10px;
	top: 70px;
	width: 40px;
	height: 40px;
	background-color: #fff;
	border: 8px solid #666;
	-webkit-border-radius: 28px;
	-moz-border-radius: 28px;
	border-radius: 28px;
}
p.thought:after
{
	width: 20px;
	height: 20px;
	left: 5px;
	top: 100px;
	-webkit-border-radius: 18px;
	-moz-border-radius: 18px;
	border-radius: 18px;
}

CSS3 thought bubble

Please see the demonstration page for an example which uses these techniques. All the CSS code is contained in the HTML source.

Have you used similar techniques to create other effects?

If you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Learn CSS3.

 

Craig Buckler

Craig is a Director of OptimalWorks, a UK consultancy dedicated to building award-winning websites implementing standards, accessibility, SEO, and best-practice techniques.

More Posts - Website

{ 36 comments }

lawrence July 12, 2011 at 5:27 am

Cool

Michael Hall March 31, 2011 at 2:22 am

i like the technique but i’ve never used the :before and :after and agree witht he other commenter that it’s too much hacking.

i’d rather just create a div or use an image that is positioned.

but very interesting tutorial.

Craig Buckler March 31, 2011 at 4:44 pm

It’s not a hack — not in the traditional browser bug sense anyway. It’s fully documented CSS behavior so it shouldn’t cause any problems. It’s certainly no worse than adding unnecessary HTML elements.

Allen April 6, 2011 at 2:14 am

Craig is right in that it’s not a hack. Perhaps it is flexing the spec a bit to accomplish something other than what was originally intended when the functionality was created… but that is still not a hack. A hack, by definition, is exploiting a flaw or bug in a spec or browser to obtain the desired result. If we didn’t push the boundaries of the spec we would never make any progress on the web and everything would still be in tables.

L L March 30, 2011 at 6:26 pm

lovely, but I can’t get the second effect accurately,no circles …

Randal March 30, 2011 at 2:38 am

Great! Think I will be using this soon in some of my sites.

Paul Lempke March 30, 2011 at 1:17 am

I think a simple vector graphic would be just as (nearly as?) compact and more generally useful . . .

Craig Buckler March 30, 2011 at 1:27 am

It would be. Unfortunately, most people (IE8 users and below) wouldn’t be able to see it. Also, only the most recent browsers support SVGs as background images.

Craig Buckler March 29, 2011 at 10:35 pm

Please publish your code somewhere and I’ll take a look.

As a thought, have you copied the code from the example above? Note there’s a scrollbar and more code appears below. If in doubt, look at the source of the demonstration page.

Edwin March 29, 2011 at 9:58 pm

I’m having the same problem. No bubbles in front of it.

Alison Garnham March 26, 2011 at 9:53 am

My speech bubble looks fine. My thought bubble does not have the circles in front of it (in Opera and Firefox). I’ve checked the code and have no idea why. Any ideas?

Neuroflux March 25, 2011 at 4:32 am

Possibly this will help as well for people viewing this:
http://css-tricks.com/examples/ShapesOfCSS/

andrej March 24, 2011 at 1:34 am

brilliant idea :)

Rudie March 23, 2011 at 7:40 pm

Very cool! Love the triangle technique.

Jesse March 23, 2011 at 6:29 pm

This is great. I’m still learning and trying to get better at coding.

It only took me about 10 minutes to punch everything in.

I guess I do have one question.

What are CSS pseudo elements and why and how can these be used?

Thanks,
Jesse

Robert March 23, 2011 at 6:00 am

I used a similar approach on http://www.dataperk.com/ awhile back, though I just used DIVs for the tail since IE7 doesn’t do :after / :before. I used dd_roundies to do the IE7/8 side of things, but you can hack your own VML code for that if you’re feeling frisky.

cat March 23, 2011 at 5:29 am

Great info and nice presentation Craig. Thanks!

Neil March 23, 2011 at 4:57 am

These are pretty innovative. Might use these in an upcoming site.

Thanks

ben March 23, 2011 at 4:56 am

Clever!
Reminds me of CSS polygons (http://tantek.com/CSS/Examples/polygons.html), though i appreciate the use of :before and :after in the article to limit the number of elements needed.

Andy Read March 23, 2011 at 4:52 am

These are clever and fun hacks, but let’s not kid ourselves: they are definitely hacks and are ‘abusing’ the semantics of CSS!

Creating triangles with bits of over-sized border: ingenious, but it’s just wrong, I’m afraid! As far as I can see, w3c does not define how different coloured borders should join at corners. It certainly explicitly states that it doesn’t define how different border styles should join at corners (http://www.w3.org/TR/2002/WD-css3-border-20021107/), so a browser could be fully compliant and not create triangles – and why should it! It’s hardly the intended semantics of ‘border’.

The use of :before and :after is also mis-using two different semantics just to means ‘append’. At a push, I’d be happier with the semantics ‘:before’ and ‘:before :before’ if that works – at least it reflects the progression of the thought bubbles :-)

I’m not trying to be overly critical, but CSS is an important step towards the semantic web and so instead of hacks like these we should be pushing for the future (CSS4?). Just like we’ve introduced semantic effects like drop-shadow, rounded-corners, inset, dash, etc. the next generation needs to add common iconic forms like ‘speech-bubble’ and ‘thought-bubble’ with parameters such as origin and offset.

This technique would probably score well in a code obfuscation competition, though :-)

Andy

Craig Buckler March 23, 2011 at 5:44 am

Abusing the semantics of CSS? That’s a new one on me!

Of course, you’re free to wait until CSS47 has a speech-bubble property, but it’s not likely to happen soon. If we go with current technologies, the alternatives to this solution are additional elements (semantically worse), images (increased bandwidth), or JavaScript (could be disabled).

Chris April 1, 2011 at 12:59 pm

@Craig, I do understand your point about CSS47, and I will personally be using this technique (as it does look good and degrade gracefully).

But surely you must admit that the point Andy made is quite valid (although the use of the word semantic is wrong). Borders are not intended to be used as triangles?

Craig Buckler April 1, 2011 at 1:15 pm

Andy mentioned that he’d like a speech/thought bubble property in CSS. I don’t think that’s likely — not soon anyway.

Border effects like this have been used for many years and all the browsers support them (including IE6). They’re not a hack and I can’t really see them causing a problem.

JT March 23, 2011 at 3:05 am

This has been out for about 3 years hehe.
Catch up bro

Karthik March 23, 2011 at 2:30 am

Great tips and helpful stuff!

Regards,
Karthik
Cogzidel Templates

powerpotatoe March 23, 2011 at 1:48 am

I love seeing & learning the simple tricks of CSS3. However, with IE’s lack of support I’m not too interested in spending the time to implement CSS3 features on my designs. Much of my web audience uses IE. I have not tried this on IE9 yet. Will it work?

Is there a similar way to create these effects in IE7 and 8? And by similar, I mean another, more convenient method besides the standard old practice of images.

Craig Buckler March 23, 2011 at 5:46 am

It works fine in IE9.

It also works in IE8, except that you don’t get rounded corners or a shadow. The speech bubble looks fine but the thought bubble looks a little blocky.

IE6 and IE7 just show the squared outer box.

kaf March 23, 2011 at 11:43 am

I call that a graceful degradation.

Cool.

McBenny March 23, 2011 at 1:10 am

Hey, nice effect ! But it’s not very flexible as you did it.
If you position the :before and :after with a top position, any resize of the bubble will break the design.
If you position them like :
p.speech:before {
bottom: -50px;
}
p.speech:after {
bottom: -30px;
}
they place themselves the same way but your bubble can grow. Of course, this is valuable if you also replace the height property of the bubble with a min-height property, that becomes very flexible.
What do you think of it ?

Craig Buckler March 23, 2011 at 5:37 am

Good call and should save a little maintenance.

bobby March 23, 2011 at 1:09 am

very good, nice short lesson.

Mo March 23, 2011 at 12:57 am

Really cool. I shall use it. Many thanks

Filippo Buratti March 23, 2011 at 12:42 am

congratulations, really simple, brilliant and beautiful!

Gaurav Mishra March 23, 2011 at 12:28 am

‘I think’ was pretty different.

Ganbold March 23, 2011 at 12:18 am

That was very cool tut.

Deb S March 23, 2011 at 12:14 am

Brilliant! – Shame about the shadow (lack of) on the pseudo-elements, still, you can’t have it all!

Comments on this entry are closed.