CSS triangles made responsive

Fixed width CSS triangles can be created easily by specifying two transparent borders and a colored border to a zero width and zero height element. Creating variable width triangles for responsive designs is not straightforward because CSS accepts border widths in pixels only. I came accross this issue recently while working on making my jQuery color picker plugin responsive.

I came up with a simple solution that uses two divs or one div and a pseudo-element to create responsive CSS triangles. Both consist of a large fixed width triangle that is covered/uncovered according to width, effectively faking responsiveness. Partially covering/uncovering the triangle makes it keep its proportions.

Now, to the code. The following are up, down, right and left pointing CSS triangles. The code is presented for both the one and two div versions. The logic used is exactly the same for both. Using two divs makes these pure CSS triangles compatible with IE7, which does not support pseudo-elements. I set up a JSFiddle for playing around with the two-div triangles: jsfiddle.net/josedvq/xEGM4 and one div triangles: jsfiddle.net/josedvq/3HG6d.

Note: For the triangles to work properly box-sizing should be set to content-box (the CSS default). Add this rule to the triangle's class if necessary.

Up-pointing CSS triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-up"><div></div></div>
.triangle-up {
	width: 25%;
	height: 0;
	padding-left:25%;
	padding-bottom: 25%;
	overflow: hidden;
}
.triangle-up div {
	width: 0; 
	height: 0;
	margin-left:-500px;
	border-left: 500px solid transparent;
	border-right: 500px solid transparent;
	border-bottom: 500px solid #4679BD;
}

This code creates a responsive triangle with base-height ratio of 2, and width 100% (of its parent). To modify this code its necessary to understand how to set the triangles proportions. In short:

(padding-left + width)/padding-bottom = (border-left + border-right)/border-bottom = base/height

margin-left = -border-left = -border-right

width = padding-left

Where base/height is the base to height ratio of the desired CSS triangle. border-left + border-right is the maximum lenght of the base and border-bottom the maximum height of the responsive triangle. Your responsive triangle won't get any bigger than the inner fixed width triangle formed by this borders. Be sure to set the px widths to values large enough and with the proportions you expect the triangle to have. This internal triangle is uncovered as width increases, so these px values determine its proportions.

The outer div must uncover the fixed width triangle keeping its proportions. In the code given the total width of the triangle is width(50%) + padding-left(50%) = 100% of its parent's width. Padding and width may be set to any other value, but should be the same for both (use 25% to create a 50% total width triangle). The total height of the outer div is height(0) + padding-bottom(50%) = 50%. Here we are taking advantage of percentages in padding being calculated against parent's width. The porportions are kept: total width/total height = 2 in the example.

For example, for an equilateral triangle base = 1.1547*height, so (border-left + border-right)/border-bottom should be base/height = 1.1547. To create a 200px maximum width equilateral triangle set border-left = border-right = 100px and border-bottom = 200/1.1547 = 173px (rounded). Then we have that (padding-left + width)/padding-bottom should also be 1.1547. Say yow want it to take 20% of its parent width. Set padding-left = 10%, width = 10% and padding-bottom = 20%/1.1547 = 18.1865%.

One-div version

<div class="triangle-up"></div>
.triangle-up {
    width: 25%;
    height: 0;	
    padding-left:25%;
    padding-bottom: 25%;
    overflow: hidden;
}
.triangle-up:after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    margin-left:-500px;
    border-left: 500px solid transparent;
    border-right: 500px solid transparent;
    border-bottom: 500px solid #4679BD;
}

Down-pointing CSS triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-down"><div></div></div>
.triangle-down{
	width: 25%;
	height: 0;
	padding-left: 25%;
	padding-top: 25%;
	overflow: hidden;
}
.triangle-down div {
	width: 0; 
	height: 0;
	margin-left:-500px;
	margin-top:-500px;
	
	border-left: 500px solid transparent;
	border-right: 500px solid transparent;
	border-top: 500px solid #4679BD;
}

Change the triangle proportions respecting:

(padding-left + width)/padding-top = (border-left + border-right)/border-top = base/height

margin-left = -border-left = -border-right

margin-top = -border-top

width = padding-left

Where base/height is the base-height ratio of the desired responsive triangle. border-left and border-right set the maximum length of the base and border-top sets the maximum height. Set this fixed width triangle to be larger than the largest triangle your layout will use. Just be sure to use the porportions you want your responsive CSS triangle to have. Then set the outer div's padding-left, padding-top and width according to these proportions (change just padding-top for total width = 100%).
For the inner div set margin-left = - border-left and margin-top = - border-top.

One-div version

<div class="triangle-down"></div>
.triangle-down {
	width: 25%;
	height: 0;
	padding-left:25%;
	padding-top: 25%;
	overflow: hidden;
}
.triangle-down:after {
	content: "";
	display: block;
	width: 0; 
	height: 0;
	margin-left:-500px;
	margin-top:-500px;
	
	border-left: 500px solid transparent;
	border-right: 500px solid transparent;
	border-top: 500px solid #4679BD;
}

Right-pointing CSS triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-right"><div></div></div>
.triangle-right {
	width: 0;
	height: 0;
	padding-top: 25%;
	padding-bottom: 25%;
	padding-left: 25%;
	overflow: hidden;
}
.triangle-right div {
	width: 0; 
	height: 0;
	margin-top:-500px;
	margin-left: -500px;
	
	border-top: 500px solid transparent;
	border-bottom: 500px solid transparent;
	border-left: 500px solid #4679BD;
}

Change the triangle proportions respecting:

(padding-top + padding-bottom)/padding-left = (border-top + border-bottom)/border-left = base/height

margin-left = -border-left

margin-top = -border-top = -border-bottom

padding-top = padding-bottom

One-div version

<div class="triangle-right"></div>
.triangle-right {
	width: 0;
	height: 0;
	padding-top: 25%;
	padding-bottom: 25%;
	padding-left: 25%;
	overflow: hidden;
}
.triangle-right:after {
	content: "";
	display: block;
	width: 0; 
	height: 0;
	margin-top:-500px;
	margin-left: -500px;
	
	border-top: 500px solid transparent;
	border-bottom: 500px solid transparent;
	border-left: 500px solid #4679BD;
}

Left-pointing CSS triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-left"><div></div></div>
.triangle-left {
	width: 25%;
	height: 0;
	padding-top: 25%;
	padding-bottom: 25%;
	overflow: hidden;
}
.triangle-left div {
	width: 0; 
	height: 0;
	margin-top:-500px;
	
	border-top: 500px solid transparent;
	border-bottom: 500px solid transparent;
	border-right: 500px solid #4679BD;
}

Change the triangle proportions respecting:

(padding-top + padding-bottom)/width = (border-top + border-bottom)/border-right = base/height

margin-top = -border-top = -border-bottom

padding-top = padding-bottom

One-div version

<div class="triangle-left"></div>
.triangle-left {
	width: 25%;
	height: 0;
	padding-top: 25%;
	padding-bottom: 25%;
	overflow: hidden;
}
.triangle-left:after {
	content: "";
	display: block;
	width: 0; 
	height: 0;
	margin-top:-500px;
	
	border-top: 500px solid transparent;
	border-bottom: 500px solid transparent;
	border-right: 500px solid #4679BD;
}

Up-right-pointing triangles

For the up-right, down-right, down-left and up-left pointing CSS triangles I'll present the one-div CSS code only. However, these can be made using two divs (for IE7 compatibility) by merely replacing the pseudo-element by another div (as in the snippets above).

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-up-right"></div>
.triangle-up-right {
    width: 0;
    height: 0;
    padding-left:25%;
    padding-top: 25%;
    overflow: hidden;
}
.triangle-up-right:after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    margin-left:-500px;
    margin-top:-500px;
    
    border-left: 500px solid transparent;
    border-top: 500px solid #4679BD;
}

Down-right-pointing triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-down-right"></div>
.triangle-down-right {
    width: 25%;
    height: 0;
    padding-top:25%;
    overflow: hidden;
}
.triangle-down-right:after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    margin-top:-500px;
    
    border-top: 500px solid transparent;
    border-right: 500px solid #4679BD;
}

Down-left-pointing triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-down-left"></div>
.triangle-down-left {
    width: 25%;
    height: 0;
    padding-bottom: 25%;
    overflow: hidden;
}
.triangle-down-left:after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    border-right: 500px solid transparent;
    border-bottom: 500px solid #4679BD;
}

Up-left-pointing triangles

The following triangle is set to take 25% of the width of its container. Resize it to see the triangle in action.

<div class="triangle-up-left"></div>
.triangle-up-left {
    width: 0;
    height: 0;
    padding-bottom: 25%;
    padding-left: 25%;
    overflow: hidden;
}
.triangle-up-left:after {
    content: "";
    display: block;
    width: 0;
    height: 0;
    margin-left: -500px;
    border-bottom: 500px solid transparent;
    border-left: 500px solid #4679BD;
}

That's it for now. I'll be writing other articles on CSS shapes soon. If you have any trouble on using these responsive CSS triangles please leave a comment below.

12 comments

  1. Hi Jose,

    I'm trying to show some text in the down-right-pointing triangle.
    I've tried the two-div-version on your JSFiddle-versions (thanks for that!) and I put some text in the inner-div:
    This is only working on the up-pointing and also on the left-pointing-versions, but on the down-right-pointing the text is not showing.
    I've tried to give the div a line-height with 130%, but this won't work, too 🙁
    Can you help, please?
    Thanks in anticipation.

  2. I'm trying to use triangles on a responsive website, where the triangles are sitting on top of an image, I'm not getting them to stay in the same position when the browser is scaled down, any ideas?

  3. Can anyone tell me how to make down-pointing and up-pointing triangles that are 100% wide (take up the full width of the content area)?

    Thanks in advance!

  4. This is awesome, but I'm stuck on how to make a down pointing triangle, e.g. 'down-right-pointing' to be 100% width. Any ideas?

Leave a Reply

Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>