Triangles are used commonly throughout interfaces. Often used to indicate current pages and the like. Whilst we can use PNGs (or JPG/GIF) I’m not a fan of that as there is no resolution independence (I for one don’t want to remake graphical assets for low/hi res each time there is a change to them).

Where possible, it makes sense to make minor UI elements like this with CSS. There are however limitations. In that case, SVG comes to our aid:

Option 1 – CSS borders and multiples for shadow effects

A common way to make triangular interface elements is by using borders. Easiest way to generate the CSS in this manner is with this online tool:

This provides the CSS. You can then either add this to an inline element (e.g. span, b, i) or use a pseudo class e.g. :before or :after (or both if you want a highlight border effect by using two laid on top of one another).

Here’s an example (SCSS) I mocked up at illustrating an example using both for a bordered triangle:

It’s also suggested to use:
-webkit-transform:rotate(360deg) for a better anti-aliasing in webkit browser – although your mileage may vary.

  • Advantages – no extra markup required, light (no image required)

  • Cons – not perfect for creating inset visual styles if you are using it with an element that has scrolling content that you need to apply overflow: hidden to.

Option 2 – A CSS box, rotated with transform

This is similar to the above option (being pure CSS) but adds a CSS3 transform into the mix. Won’t work on ailing browsers but not bad elsewhere. Same inset visual style issues/limitations apply as before, but making a bordered edge is easy as you can add a border to just two adjoining sides and then rotate it.

One extra mark against this technique though is that the triangle must be equilateral (as its made from half a square). The border based technique doesn’t suffer this limitation.

Here’s an example (SCSS):

Option 3 – using an SVG image

This is one way to get exactly what you need. For a small UI element like this, it’s probably best to inline it. For more info on that practice, see this related post

The other great thing about doing it with SVG is that it can scale to a containers size (where the other prior versions won’t). Therefore it the size of the container is set with ems and something ‘up the chain’ changes, SVG will just work (as long as the SVG is made to be height and width 100% natively or set that way with CSS).

Option 4 – Use an icon font (best)

If you want the crispness of SVG and the versatility of border colours, use an icon font. That way you can make the triangle however you need it (isosceles for example) and then use color and text-shadow to add the shadow – beautiful! That’s the way I’ve been doing mine lately as it seems to offer the best all around solution. Need to make an icon font? This post might help.

Some common gotchas to resolution independent triangles/shapes:

  • Remember that box-shadow won’t work around them (it adds shadow to the outside of the invisible box that positions the element)

  • The newer filter: drop-shadow() respects the outline of the object (as it’s applied after the page has been rendered so be aware of the performance considerations – tip less blur equals less strain on device/browser) so good for drop-shadows but can’t be used for inset shadows (filter: drop-shadow() doesn’t do insets).

    Also, whilst the situation is likely to improve, as filters after the entire page has been saved as a bitmap, I get fuzzy looking text on elements that have had a drop-shadow applied.

My latest book, 'Enduring CSS' is out now

Get $5 off HERE ↠

Write and maintain large scale modular CSS and embrace modern tooling including PostCSS, Stylelint and Gulp