CSS Triangles

By  on  

This post has been updated to include CSS triangles without markup via :before and :after pseudo-elements.

CSS Triangles

I was recently redesigning my website and wanted to create tooltips.  Making that was easy but I also wanted my tooltips to feature the a triangular pointer.  I'm a disaster when it comes to images and the prospect of needing to make an image for every color tooltip I wanted made me rethink my redesign.  Lucky for me, MooTools Core Developer Darren Waddell shared with me a great trick:  CSS triangles.  Using pure CSS you can create cross-browser compatible triangles with very little code!

The CSS

/* create an arrow that points up */
div.arrow-up {
	width: 0; 
	height: 0; 
	border-left: 5px solid transparent;  /* left arrow slant */
	border-right: 5px solid transparent; /* right arrow slant */
	border-bottom: 5px solid #2f2f2f; /* bottom, add background color here */
	font-size: 0;
	line-height: 0;
}

/* create an arrow that points down */
div.arrow-down {
	width: 0; 
	height: 0; 
	border-left: 5px solid transparent;
	border-right: 5px solid transparent;
	border-top: 5px solid #2f2f2f;
	font-size: 0;
	line-height: 0;
}

/* create an arrow that points left */
div.arrow-left {
	width: 0; 
	height: 0; 
	border-bottom: 5px solid transparent;  /* left arrow slant */
	border-top: 5px solid transparent; /* right arrow slant */
	border-right: 5px solid #2f2f2f; /* bottom, add background color here */
	font-size: 0;
	line-height: 0;
}

/* create an arrow that points right */
div.arrow-right {
	width: 0; 
	height: 0; 
	border-bottom: 5px solid transparent;  /* left arrow slant */
	border-top: 5px solid transparent; /* right arrow slant */
	border-left: 5px solid #2f2f2f; /* bottom, add background color here */
	font-size: 0;
	line-height: 0;
}

The secret to these triangles is creating giant borders to the two perpendicular sides of the direction you'd like the triangle to point. Make the opposite side's border the same size with the background color of whatever color you'd like the tooltip to be.  The larger the border, the larger the triangle.  You can color your triangles any color, any size, and in any direction. The best part is that there's very little code needed to achieve this effect.

CSS Triangles with :before and :after

The CSS examples above uses true elements but what if you don't want to add single triangles? CSS triangles can be created with pseudo-elements; this is the perfect case for tooltips. Here's how you can do so:

div.tooltip {
	/* tooltip content styling in here; nothing to do with arrows */
}

/* shared with before and after */
div.tooltip:before, div.tooltip:after {
	content: ' ';
	height: 0;
	position: absolute;
	width: 0;
	border: 10px solid transparent; /* arrow size */
}

/* these arrows will point up */

/* top-stacked, smaller arrow */
div.tooltip:before {
	border-bottom-color: #fff;  /* arrow color */

	/* positioning */
	position: absolute;
	top: -19px;
	left: 255px;
	z-index: 2;
}

/* arrow which acts as a background shadow */
div.tooltip:after {
	border-bottom-color: #333;  /* arrow color */

	/* positioning */
	position: absolute;
	top: -24px;
	left: 255px;
	z-index: 1;
}

The border side you add the color to is the opposite side of the arrow pointer. Also not that you don't need to use both :before and :after pseudo-elements -- you need only use one. The second arrow could, however, be used as a background shadow or background "border".

I don't know how I didn't know about this technique sooner!  This neat trick will surely help me in the future and opens up a world of possibilities for me to improve existing tooltip elements.

Recent Features

  • By
    Welcome to My New Office

    My first professional web development was at a small print shop where I sat in a windowless cubical all day. I suffered that boxed in environment for almost five years before I was able to find a remote job where I worked from home. The first...

  • By
    Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API...

Incredible Demos

  • By
    AJAX For Evil:  Spyjax with jQuery

    Last year I wrote a popular post titled AJAX For Evil: Spyjax when I described a technique called "Spyjax": Spyjax, as I know it, is taking information from the user's computer for your own use — specifically their browsing habits. By using CSS and JavaScript, I...

  • By
    MooTools’ AutoCompleter Plugin

    One of the famous MooTools plugins is Harald Kirschner's AutoCompleter plugin. AutoCompleter takes a term input by the user and searches for matches -- an obviously help to the user. Here's how to make the most of Harald's great plugin. The XHTML All we...

Discussion

  1. Alex Simon

    whoa! what am I missing here? – where are the browser hacks, the js, etc?
    Surly it can’t be that easy!

  2. @Alex Simon: That’s exactly what I was thinking! This is weird, incredible, and I can’t figure out why it’s working.

  3. It’s a 0 pixel element in the middle, and browsers render border edges slanted which creates the border. It’s a great trick indeed. You can also do it with pseudo-elements, something like this:


    .tooltip:before {
    content: '';
    display: block;
    width: 0;
    height: 0;
    border: 5px solid;
    border-color: #2f2f2f transparent transparent;
    }

  4. Awesomeness!!! Can’t wait to try this with a slider i’m working on. Perfect for the next, prev buttons…

  5. It seems that CSS is more and more self-sufficient. Great example, thanks.

  6. Binyamin

    For IE6 you need to use in css color, transparent does not work.

  7. WTF?
    Way better then my previous Solution (before-content set to unicode-Triangles), although i have to admit its pretty hard to understand why it works that way.
    Still.. have to try this in my private projects.

  8. Wait a minute Walsh, so you DIDN’T read my blog post about this months ago? Now I’m just a bit sad…

  9. @Eric Wendelin: Mine is more focused on the triangle itself, plus you wrote that in Feb. I dont’ remember what *I* wrote in February.

  10. I’ve been using this for at least a year now so it’s nothing new and requires no special CSS3 or anything. Nice to have a good resource for them though, I always use them for dropdowns and what not.

  11. I’ve been using CSS triangles on my site http://donatstudios.com for quite a while – notice on the right under the headers, the little triangle – I hate images and that was a nice way around it.

  12. Also I, based http://jsfiddle.net/Fk3Kj/ on the concept a back in February

    @Jesse G. Donat:

  13. It’s easier to visualise when you see this:

    http://jsfiddle.net/ctCXY/

    The font-size of 0px (or line-height: 0px, or overflow: hidden) may be needed for IE6 in some cases.

  14. I looked at how the borders are created and it makes sense as to why it would result in a triangular look. I continuously get designs with a lot triangles. Ingenious! Thanks for the tip!

  15. @David Walsh: Heh, no worries :)

    Do you get the idea that CSS is getting much more verbose lately?

    • A bit. I’m just glad the we seem to be moving forward.

  16. David Workman

    Great :) Took me a minute or so to figure out why it worked like that but not a trick I’ll be forgetting in a hurry :)

    For those still wondering why it works, do the following:

    – Draw a square on a piece of paper
    – Draw in the diagonals of the square so you have a box made of 4 triangles.

    What you have on the paper in front of you now is the border regions of a 0x0 element in the CSS model.

  17. TheToolman

    I saw this technique quite a long time ago on this 3D javascript demo:

    http://www.uselesspickles.com/triangles/demo.html

    The link above shows how triangles of arbitrary shape can be made from a group of these right angle triangles.

  18. There’s more info on this here (courtesy of Jon Rohan), http://www.dinnermint.org/css/creating-triangles-in-css/

    “Few people realize when a browser draws the borders, it draws them at angles. This technique takes advantage of that. One side of the border is colored for the color of the arrow, and the rest are transparent. Then you set the width of the border to something large”

    Hedger Wang also recently posted this, http://hedgerwow.appspot.com/demo/arrows which looks like you no longer need a filter for transparency in IE.

  19. How about some css shadows?

  20. Do css shadows work on those triangles?

  21. Wow, that’s neat

    Thanks for the great tip

  22. For anyone who has to deal with IE6, this technique will work in that browser if you give the borders a color instead of having them be transparent.

  23. Nice! —the same idea could be extended to create a “V” shape ( for tooltips, etc.) by positioning a second smaller triangle on top if the first ( say a white triangle on top of a larger black triangle ).

  24. Michael

    You should add line-height: 0; font-size: 0; for IE, especially if you are supporting v6

  25. I can’t believe no-one’s mentioned CSS Play yet – Stu’s done some crazy stuff with borders in the page, check out this flag! http://www.cssplay.co.uk/menu/flag

    If you’ve not been there before, check out his demos – they’ve been around for about 4+ years now I think but are still really fun to dissect with Firebug.

  26. Dutchie

    Yea, CSS FTW I say, f#ck JS

  27. Jean-Philippe HALIMI

    Still, there is a problem with this technique ; it seems there is no way to add borders to the triangle. Anyway, nice trick, indeed :o)

  28. Amazing !!
    ¡¡ Increíble tío !!

  29. /* IE6 */
    .chat-bubble-arrow {
    _border-left-color: pink;
    _border-bottom-color: pink;
    _border-right-color: pink;
    _filter: chroma(color=pink);
    }

  30. Also take a look at the control bar of this html5 player
    http://videojs.com/
    all html+css, same methods.. bye!

  31. Lachlann

    Great trick, has any one else tried creating an isosceles triangle by adjusting the border sizes? works fine in Firefox but looks very pixelated in chrome safari

    Any ideas?

    L

  32. It says div.arrow-left twice in your example css.

  33. This is cool, but not new. A co-worker of mine came up with this technique about 4 years ago, he even has a workaround for versions of IE that don’t support transparent borders. Check out his example of 3d rendering using triangles http://www.uselesspickles.com/triangles/ His blog also has a better visual explanation of how the transparent borders make the div become a triangle, this post keeps it a mistery.

  34. In case anyone was annoyed by the tiny dark outline that browsers leave around the edges of CSS triangles such as these, you can set the border-style of the transparent borders to dotted and it will make them go away ;)

    • KTB

      Thank you very much.

  35. Oh, and on browsers that support rgba(), setting the transparent border side colors to rgba(255, 255, 255, 0) works as well.

    • Danielle Kinney

      Daniel,

      You are a amazing!

      I have been searching for a solution to the dark outline issue in FF.

      THANK YOU SO MUCH!

  36. Wow David this works perfectly across browser. Nice

  37. I’m using a similar method, but using the pseduo element before to add the arrow. Can’t get the arrow to show up in IE 8. Ever run in this?

  38. Britto

    Works perfectly.. Thx

  39. Person

    Open sans is terrible, completely terrible.

  40. Dr. Clue

    While most folks gained their first excitment using CSS triangles to dispose of images, now the fun part is with CSS3 and actually using the same border arrow trick , but this time with the border image property to texturize the triangles in 3D, to make cool egyption pyramids.

    Just remember when you put your texture togeather that same gets diced up like a tic-tac-toe board and you need them lower left and right squares to be divided diagnally as appropriate for each of the two corners each half transparent and half texture. (Not really hard , just a few minutes in InkScape)

  41. Peter Galiba

    The sad thing, if the triangles doesn’t have 45˚ sides it looks really pixelated in Firefox. Other browsers are really fine, specially in mobile Safari, as it can use the retina display to create sharp edges there. It looks the worse on mobile and Windows Firefox, on Mac it is better but still far from ideal. IE, Chrome and Safari looks excellent and the OS doesn’t matter even (where supported) and even non-blink Opera is better.

  42. Mike

    @mixin caret($position, $width, $color) {
    &:after {
    border: $width solid transparent;
    content: ”;
    position: absolute;
    #{$position}: -(2 * $width);

    @if $position == right {
    border-left-color: $color;
    top: 50%;
    @include experimental-value(top, calc(50% – #{$width}));
    }
    @else if $position == left {
    border-right-color: $color;
    top: 50%;
    @include experimental-value(top, calc(50% – #{$width}));
    }

    @else if $position == top {
    border-bottom-color: $color;
    left: 50%;
    @include experimental-value(left, calc(50% – #{$width}));
    }
    @else if $position == bottom {
    border-top-color: $color;
    left: 50%;
    @include experimental-value(left, calc(50% – #{$width}));
    }
    }
    }

  43. Florian

    There are so many possibilities of geometric CSS shapes. CSS-Tricks listed some really interesting ones:
    http://www.css-tricks.com/examples/ShapesOfCSS
    Even Yin Yang is among them. ;-)

  44. only one word for this tutorial it is really “amazing” thanks for this post :)

    Regards
    Rahul Kashyap

  45. Great trick, tnx

    (Hope I’m not missing something) I think there is a small typo in the markup of your Pseudo-Element demo ( the enclosing div has id = “position:relative;” should have style=…. )

  46. Ted

    There were two major downsides I found with this solution which made me very sad. 1) In certain circumstances (I saw it on high DPI displays) there was a hair’s-width line between the triangle and the attached rectangle. Second, it doesn’t work on display: table-cell, so its use for a row of tabs is limited.

  47. Anil Namde

    I am trying to extent it to create image/document section separator (http://tympanus.net/Development/SectionSeparators/) in page. However as we have to mention size in pixel not sure how it would help with responsive design.

    Is there any way it can be extended to fit for responsive design ?

  48. Can this be done with background elements ?

  49. Pablo S.

    Great. Someone could describe the advantages of this technique instead of using, let’s say, images?

  50. Rashmi

    Its a nice and simple solution. You saved me a lot of headache.
    Thank you.

  51. Thank you sir! I’m using a modified version of your code and can confirm it works on IE9 through 11, Edge 12 and 13, Chrome (Mac and Win), Firefox (Mac and Win), and Safari.

    I used https://www.browserstack.com/ to test.

  52. I am using the triangle code with the bootstrap dropdown menu but how i can change the color of the triangle when i hover the first element of the dropdown. Here is the code

    .dropdown-menu::before {
        border-bottom: 15px solid rgba(0, 0, 0, 0.2);
        border-left: 15px solid rgba(0, 0, 0, 0);
        border-right: 15px solid rgba(0, 0, 0, 0);
        content: "";
        display: inline-block;
        left: 20px;
        position: absolute;
        top: -15px;
    }
      .dropdown-menu::after {
        border-bottom:15px solid #FFFFFF;
        border-left:15px solid rgba(0, 0, 0, 0);
        border-right:15px solid rgba(0, 0, 0, 0);
        content: "";
        display: inline-block;
        left: 20px;
        position: absolute;
        top: -14px;
      }
    
  53. Lÿo

    Instead of using absolute position, is it possible to center the triangle pointer regardless of the width of the tooltip?

    • Lÿo

      Got my answer already thanks.

      margin-left: auto;
      margin-right: auto;
      left: 0;
      right: 0;
      
  54. Dennis

    Hey Walsh, i really would like to know exactly why it works. Why giving border to a element with no height or width it draws a triangle? I think it’s awesome, but i dont understang why that happen. Any explanation or reading would be great! thank you! awesome post!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!