10 November 2009

A cross-browser callout box using CSS border triangles. For ie6 too!

This post describes how to use CSS border triangles (or slants) to successfully add a notch to a callout box—with no images and minimal markup—in a cross-browser way that even works in internet explorer 6 (ie6). If you’re already familiar with this general technique jump to the code.

This is how the end result looks

The basics:

In CSS you can control the border on each side of an html box element (top, right, bottom, and left) separately. So instead of “border:1px solid #000” you can do stuff like “border-left:1px solid #000”. This means that you can give different colors and sizes to each border.

This gets interesting as you decrease the height and width of a box, but increase the border width.

You can also play with the colors:

And more importantly you can assign different widths to each border:

Transparent borders:

As seen in the last color example, we only want to color one border. Instead of setting the other borders to white, we can do better and allow our notch to appear over any type of background by making the non-notch borders transparent. Mostly all browsers support border-color: transparent, except for ie6, which requires a hack. We can solve this problem for ie6 by using “_” to target just this browser and then this popular chroma hack:

.notch {
    border-top: 10px solid #000;
    border-right: 10px solid transparent;
    border-left: 10px solid transparent;
    border-bottom: 0;
    _border-right-color: pink;
    _border-left-color: pink;
    _filter: chroma(color=pink);
}

note: I find the underscore hack easier than using conditional comments, but you could take that approach if you wanted.

Non-jagged angles:

Various browsers end up with jagged edges when you create these arrows. The safest angle to get your arrow to render without jaggies is 45%. This can be done by just making all the border-widths the same except for one being zero (as done in the example code above). This matters the most if you want a border around your notch.

Position absolute and mysterious height:

Ie6 will mysteriously ignore a specified height on an empty element that is absolutely positioned and assign its own height. The solution for this is easy, just set font-size and line-height both to zero in CSS. Otherwise, the arrow will appear inside the callout box. I encountered this problem when I wrote the low res paint app.

The final code:

The markup looks like this:

<div class="callout">
    This is a callout box!
    <b class="notch"></b>
</div>

Note: I like to reserve elements like “b”, “u”, “s”, and “i” for special, non-text content, design cases like this one, which makes them stand out more easily in code and it’s also less characters to write.

and the CSS looks like this (using arbitrary padding and margin from my site):

.callout {
    position: relative;
    margin: 18px 0;
    padding: 18px 20px;
    background-color: #eef4f9;
    /* easy rounded corners for modern browsers */
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
}
.callout .notch {
    position: absolute;
    top: -10px;
    left: 20px;
    margin: 0;
    border-top: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-bottom: 10px solid #eef4f9;
    padding: 0;
    width: 0;
    height: 0;
    /* ie6 height fix */
    font-size: 0;
    line-height: 0;
     /* ie6 transparent fix */
    _border-right-color: pink;
    _border-left-color: pink;
    _filter: chroma(color=pink);
}

Note: I’m clearly diverging from my ie6 (and general ie) support by doing the border-radius rounded corners, but I think this is a much better approach than doing nothing at all, and it rewards those who have seen the light or aren’t using an un-upgradable computer at work.

and here’s that code rendered as a callout with a notch:

This is a callout box!

Let’s add a border:

With just a little more markup

<div class="callout border-callout">
    This is a callout box with a border!
    <b class="border-notch notch"></b>
    <b class="notch"></b>
</div>

and a little more CSS

.border-callout { border: 1px solid #c5d9e8; padding: 17px 19px; }
.border-callout .border-notch { border-bottom-color: #c5d9e8; top: -11px; }

we can add a border around the callout that follows the notch.

This is a callout box with a border!

Additional Internet Explorer Pitfalls

  • If the callout box is inside a div that hasLayout, then you might need to apply layout to the callout box to get the borders to appear properly for ie6 and ie7. Either give it a height or width or just add this to its CSS: zoom: 1;
  • If the callout box positions itself funny, you may need to set its parent elements to also have position: relative

The benefits of this technique:

  • Minimal markup (but more CSS, which I think is a good trade-off)
  • No images (quicker page load)
  • Very easy to modify the colors, size, and shape
  • Can appear over any background (due to transparent borders)

Comments (25)

1. Vinay wrote:
<p> This is pretty sweet :) now i just need to think of something that needs callout boxes... </p>

Posted on 10 November 2009 at 8:11 PM  |  permalink

2. peter wrote:
<p> I’m sure the opportunity will arise at some point, just don’t force it :) Btw, the notch also looks good on the left side of the box. </p>

Posted on 12 November 2009 at 11:11 AM  |  permalink

3. ldii wrote:
<p> Great lesson I&#39;ve never found in html editor feature. Thank you. </p>

Posted on 26 December 2009 at 5:12 PM  |  permalink

4. Tom wrote:
<p> I&#39;m having problems getting a border on the top of the triangle when I change it to point left. </p>

Posted on 25 May 2010 at 5:05 PM  |  permalink

5. peter wrote:
<p> Hey Tom, you want the border notch to appear to the left (not top) of the triangle when it is pointing left. If that didn’t help, try commenting out the &lt;b class=&quot;notch&quot;&gt;&lt;/b&gt;, so just the &lt;b class=&quot;border-notch notch&quot;&gt;&lt;/b&gt; is inside your callout, and see if it is rendering in the correct spot—using something like firebug might also help to see where it is getting rendered. If you’re still stuck, try posting some code—it’s really hard to debug code when you can’t see it :) </p>

Posted on 26 May 2010 at 10:05 AM  |  permalink

6. Silviya Howe wrote:
<p> Very interesting and usefull. Thank you for this help </p>

Posted on 23 August 2010 at 5:08 PM  |  permalink

7. James wrote:
<p> This is an ingenious solution to a not-so-straight forward problem. </p> <p> It was very useful for some consultancy work I did. </p> <p> Thanks very much. </p>

Posted on 14 November 2010 at 4:11 PM  |  permalink

8. peter wrote:
<p> Awesome, I’m glad it helped! </p>

Posted on 14 November 2010 at 9:11 PM  |  permalink

9. Rick Evans wrote:
<p> I cannot get the rounded corners in IE 7 but it works perfectly in Safari. You page does not show rounded corners in IE either. Any suggestions? </p>

Posted on 12 January 2011 at 10:01 AM  |  permalink

10. peter wrote:
<p> Hey Rick, unfortunately the rounded corners are not supported in IE6, IE7, or IE8. However, it’s a nice progressive enhancement for the browsers that do support it. I’m fine with that, but you can find tons of tutorials to do cross-browser rounded corners with a google search. </p>

Posted on 12 January 2011 at 12:01 PM  |  permalink

11. Garrett wrote:
<p> Awesome tutorial! Just one question: I was wondering what tinkering it would take to get the notch on the bottom on the callout or on the left side. I messed with it a bit but it didn&#39;t cooperate. Thanks! </p>

Posted on 17 March 2011 at 7:03 PM  |  permalink

12. peter wrote:
<p> Hey Garrett, to get stuff on the left side instead of the top, you basically just change every instance of the word top in the css to left, bottom to right, left to top, and right to bottom. </p> <p> I’d also recommend using the firebug extension on firefox so you can inspect HTML elements on a page you’re building and even change CSS rules within your browser. </p>

Posted on 17 March 2011 at 10:03 PM  |  permalink

13. psalms wrote:
<p> you have no idea how long i have been searching for a way to do this. Thanks for your help! </p>

Posted on 1 May 2011 at 8:05 PM  |  permalink

14. Sam wrote:
<p> This is a great technique. However it doesn&#39;t seem to work perfectly in ie8 - the pointer doesn&#39;t overlap the box properly, so the arrow doesn&#39;t appear to be part of the box, just stuck on top of it. I am using ie tester to check this, so perhaps it would be ok if I used ie8 out of the box. </p>

Posted on 12 May 2011 at 5:05 PM  |  permalink

15. peter wrote:
<p> Hey Sam, when I try it in IE8 it works perfectly—at least, in the examples on this page. Does ie tester show the same bugs on this page too? </p>

Posted on 13 May 2011 at 6:05 PM  |  permalink

16. David wrote:
<p> Awesome post. Used it for the notch in a few projects a few months back but today, I came up with a new use for this. I used the techniques here to create CSS only previous and next &quot;arrows&quot; on a content rotator built using jQuery&#39;s Cycle plugin. Worked a charm and no nasty images to manage. </p>

Posted on 6 July 2011 at 8:07 PM  |  permalink

17. peter wrote:
<p> @david, thanks, that’s a great use for CSS triangles! I used that technique for the image browser in my Scroll Sneak demo: http://mrcoles.com/scroll-sneak/ </p>

Posted on 7 July 2011 at 10:07 AM  |  permalink

18. radiant wrote:
<p> Great!! Combinig it with jQuery, it would be a cool plugin that could be used for showing notifications or validation errors..May be I&#39;ll write one this weekend. Thanks for sharing </p>

Posted on 14 September 2011 at 8:09 AM  |  permalink

19. webdev wrote:
<p> Thank you so much for this! It helped me a lot. Worked like a charm </p>

Posted on 15 February 2012 at 1:02 PM  |  permalink

20. John wrote:
<p> Very helpful. Is there a way to position the notch some distance from the right, rather than from the left, of the callout? </p>

Posted on 18 March 2012 at 10:03 AM  |  permalink

21. CJ wrote:
<p> John, change the css on the .callout .notch cselector. Change &quot;left:20px&quot; to &quot;right:20px&quot; or whatever you want. </p>

Posted on 27 March 2012 at 9:03 AM  |  permalink

22. Allison wrote:
<p> This is a very cool way to do notches...I&#39;m using it on a site and in Firefox under Windows 7, I&#39;m getting a strange border on the border - there&#39;s a 1px grey border around my notch...I thought maybe it was inheriting a box-shadow or text-shadow, but it&#39;s not...I don&#39;t even know where that color is coming from. Has anyone seen this or know what could be causing it? </p>

Posted on 13 April 2012 at 5:04 PM  |  permalink

23. zvikico wrote:
<p> @Allison, just encountered the problem myself. Checkout the following SO question: http://stackoverflow.com/questions/6225284/css-transparent-border-problem-in-firefox-4 </p> <p> The solution is to use rgba(255,255,255,0) instead of transparent. However, this will break IE, so you should use transparent first and rgba(255,255,255,0) later. Something like this: </p> <pre><code>.callout .notch { ..... border-left: 10px solid transparent; border-left: 10px solid rgba(255,255,255,0); border-right: 10px solid transparent; border-right: 10px solid rgba(255,255,255,0); .... } </code></pre>

Posted on 17 April 2012 at 2:04 AM  |  permalink

24. kathir wrote:
<p> How to change the callout pointer top to left side. </p>

Posted on 21 May 2012 at 5:05 AM  |  permalink

25. Marmoset wrote:
<p> Very clean and elegant solution. Works great with my dynamic tool tips - thanks for sharing! </p>

Posted on 14 September 2012 at 1:09 PM  |  permalink

Peter Coles

Peter Coles

is a software engineer who lives in NYC, works at Ringly, and blogs here.
More about Peter »

github · soundcloud · @lethys · rss

It’s time to get big money out of politics. Join the kick-started campaign to put government back in the hands of the people. Pledge mayday.us now