How to make oblique endings of after and before elements? - css

you can see a pic below (I am really bad at painting, sorry for that). I don't know how to make these (I guess) box-shadows (pink in the picture) only on two corners, but their ending is oblique. Because what I think, those borders (red in the picture) on corners can be made with after and before elements.
What I would do is to make two boxes, one inside the other and add a box shadow. But I stop at that point how to make those oblique endings and how to make those shadows shorter than the whole height or length. Maybe you have any ideas?
this is what i have tries so far:
.div2 {
position: relative;
width: 40px;
height: 40px;
margin: 10px;
}
.div {
position: relative;
width: 60px;
height: 50px;
margin: 20px;
box-shadow: 10px 10px;
}
.div2::before {
display: block;
content: "";
width: 20px;
height: 20px;
position: absolute;
top: -10px;
left: -10px;
border-top: 1px solid #000;
border-left: 1px solid #000;
}
span::after {
display: block;
content: "";
width: 20px;
height: 20px;
position: absolute;
bottom: -10px;
right: -10px;
border-bottom: 1px solid #000;
border-right: 1px solid #000;
}
<div class="div">
<div class="div2"><span></span></div>
</div>

about gradient see : https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient
The linear-gradient() CSS function creates an image consisting of a progressive transition between two or more colors along a straight line. Its result is an object of the <gradient> data type, which is a special kind of <image>.
about multiple background https://css-tricks.com/css-basics-using-multiple-backgrounds/
& https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders/Using_multiple_backgrounds
You can apply multiple backgrounds to elements. These are layered atop one another with the first background you provide on top and the last background listed in the back. Only the last background can include a background color.
background-size is also usefull here https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
The background-size CSS property sets the size of the element's background image. The image can be left to its natural size, stretched, or constrained to fit the available space.
background-clip comes handy too https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip
The background-clip CSS property sets whether an element's background or extends underneath its border.
playing around with background-^properties you could do something like this
.mybox {
width:250px;
height:180px;
padding:20px;
background:
linear-gradient(0deg,rgb(237, 28, 36),rgb(237, 28, 36)),
linear-gradient(0deg,rgb(237, 28, 36),rgb(237, 28, 36)),
linear-gradient(0deg,rgb(237, 28, 36),rgb(237, 28, 36)),
linear-gradient(0deg,rgb(237, 28, 36),rgb(237, 28, 36)),
linear-gradient(0deg, rgb(0, 162, 232), rgb(0, 162, 232)),
linear-gradient(-45deg, rgb(255, 174, 201) 20%, rgb(0, 162, 232) 20%, rgb(0, 162, 232) 80%, rgb(255, 174, 201) 80%) ;
background-clip: border-box, border-box,border-box, border-box, content-box,border-box;
background-repeat:no-repeat;
background-size: 3px 40px, 80px 3px, 3px 40px, 80px 3px,auto auto,auto auto;
background-position: 22px 160px, 22px 200px , 260px 15px , 180px 15px ,center, center;
display:flex;
align-items:center;
justify-content:center;
color:white;
font-size:3rem;
box-shadow: 20px 20px 10px purple
}
<div class="mybox"> My Box</div>

Here is my idea using multiple background and border-image
.box {
width:150px;
height:100px;
border:15px solid transparent;
border-image:linear-gradient(-45deg,pink 20%,transparent 20%,transparent 80%,pink 80%) 15;
background:
linear-gradient(red,red) top right,
linear-gradient(red,red) top right,
linear-gradient(red,red) bottom left,
linear-gradient(red,red) bottom left,
#00a2e8;
background-size:2px 40px,40px 2px;
background-origin:padding-box;
background-repeat:no-repeat;
}
<div class="box"></div>
Here is another idea using less gradient:
.box {
width:150px;
height:100px;
border:15px solid transparent;
border-image:linear-gradient(-45deg,pink 20%,transparent 20%,transparent 80%,pink 80%) 15;
background:#00a2e8;
position:relative;
}
.box:before {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:2px solid transparent;
border-image:linear-gradient(30deg,red 20%,transparent 20%,transparent 80%,red 80%) 1;
}
<div class="box"></div>

Related

Triangle Div -- With Border-image [duplicate]

There're plenty of different CSS shapes over at CSS Tricks - Shapes of CSS and I'm particularly puzzled with a triangle:
#triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div id="triangle-up"></div>
How and why does it work?
CSS Triangles: A Tragedy in Five Acts
As alex said, borders of equal width butt up against each other at 45 degree angles:
When you have no top border, it looks like this:
Then you give it a width of 0...
...and a height of 0...
...and finally, you make the two side borders transparent:
That results in a triangle.
The borders use an angled edge where they intersect (45° angle with equal width borders, but changing the border widths can skew the angle).
div {
width: 60px;
border-width: 30px;
border-color: red blue green yellow;
border-style: solid;
}
<div></div>
Have a look to the jsFiddle.
By hiding certain borders, you can get the triangle effect (as you can see above by making the different portions different colours). transparent is often used as an edge colour to achieve the triangle shape.
Start with a basic square and borders. Each border will be given a different color so we can tell them apart:
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 200px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
which gives you this:
But there's no need for the top border, so set its width to 0px. Now our border-bottom of 200px will make our triangle 200px tall.
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
and we will get this:
Then to hide the two side triangles, set the border-color to transparent. Since the top-border has been effectively deleted, we can set the border-top-color to transparent as well.
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
finally we get this:
Different approach:
CSS3 triangles with transform rotate
Triangular shape is pretty easy to make using this technique. For people who prefer to see an animation explaining how this technique works here it is :
Link to the ANIMATION : How to make a CSS3 triangle.
And DEMO : CSS3 triangles made with transform rotate.
Otherwise, here is detailed explanation in 4 acts (this is not a tragedy) of how to make an isosceles right-angled triangle with one element.
Note 1 : for non isosceles triangles and fancy stuff, you can see step 4.
Note 2 : in the following snippets, the vendor prefixes aren't included. they are included in the codepen demos.
Note 3 : the HTML for the following explanation is always : <div class="tr"></div>
STEP 1 : Make a div
Easy, just make sure that width = 1.41 x height. You may use any techinque (see here) including the use of percentages and padding-bottom to maintain the aspect ratio and make a responsive triangle. In the following image, the div has a golden yellow border.
In that div, insert a pseudo element and give it 100% width and height of parent. The pseudo element has a blue background in the following image.
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr: before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
}
STEP 2 : Let's rotate
First, most important : define a transform origin. The default origin is in the center of the pseudo element and we need it at the bottom left. By adding this CSS to the pseudo element :
transform-origin:0 100%; or transform-origin: left bottom;
Now we can rotate the pseudo element 45 degrees clockwise with transform : rotate(45deg);
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 3 : hide it
To hide the unwanted parts of the pseudo element (everything that overflows the div with the yellow border) you just need to set overflow:hidden; on the container. after removing the yellow border, you get... a TRIANGLE! :
DEMO
CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
overflow: hidden;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 4 : go further...
As shown in the demo, you can customize the triangles :
Make them thinner or flatter by playing with skewX().
Make them point left, right or any other direction by playing with the transform origin and rotation direction.
Make some reflexion with 3D transform property.
Give the triangle borders
Put an image inside the triangle
Much more... Unleash the powers of CSS3!
Why use this technique?
Triangle can easily be responsive.
You can make a triangle with border.
You can maintain the boundaries of the triangle. This means that you can trigger the hover state or click event only when the cursor is inside the triangle. This can become very handy in some situations like this one where each triangle can't overlay its neighbours so each triangle has its own hover state.
You can make some fancy effects like reflections.
It will help you understand 2d and 3d transform properties.
Why not use this technique?
The main drawback is the browser compatibility, the 2d transform properties are supported by IE9+ and therefore you can't use this technique if you plan on supporting IE8. See CanIuse for more info. For some fancy effects using 3d transforms like the reflection browser support is IE10+ (see canIuse for more info).
You don't need anything responsive and a plain triangle is fine for you then you should go for the border technique explained here : better browser compatibility and easier to understand thanks to the amazing posts here.
Here is an animation in JSFiddle I created for demonstration.
Also see snippet below.
This is an Animated GIF made from a Screencast
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0', 'margin-top': '120'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 20px 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Random version
/**
* Randomize array element order in-place.
* Using Durstenfeld shuffle algorithm.
*/
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
transforms = shuffleArray(transforms)
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
All at once version
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
$(this)
.animate({'border-top-width': 0 ,
'border-left-width': 30 ,
'border-right-width': 30 ,
'border-bottom-width': 80 ,
'width': 0 ,
'height': 0 ,
'margin-left': 100,
'margin-top': 150,
'borderTopColor': 'transparent',
'borderRightColor': 'transparent',
'borderLeftColor': 'transparent'}, duration)
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Lets say we have the following div:
<div id="triangle" />
Now Edit the CSS step-by-step, so you will get clear idea what is happening around
STEP 1:
JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid black ;
border-right: 50px solid black;
border-bottom: 50px solid black;
border-top: 50px solid black;
}
This is a simple div. With a very simple CSS. So a layman can understand. Div has dimensions 150 x 150 pixels with the border 50 pixels. The image is attached:
STEP 2: JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the border-color of all 4 sides. The image is attached.
STEP:3 JSfiddle Link:
#triangle {
background: purple;
width :0;
height:0;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the height & width of div from 150 pixels to zero. The image is attached
STEP 4: JSfiddle:
#triangle {
background: purple;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I have made all the borders transparent apart from the bottom border. The image is attached below.
STEP 5: JSfiddle Link:
#triangle {
background: white;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I just changed the background color to white. The image is attached.
Hence we got the triangle we needed.
And now something completely different...
Instead of using css tricks don't forget about solutions as simple as html entities:
▲
Result:
▲
See: What are the HTML entities for up and down triangles?
Consider the below triangle
.triangle {
border-bottom:15px solid #000;
border-left:10px solid transparent;
border-right:10px solid transparent;
width:0;
height:0;
}
This is what we are given:
Why it came out in this shape? The below diagram explains the dimensions, note that 15px was used for the bottom border and 10px was used for left and right.
It's pretty easy to make a right-angle triangle also by removing the right border.
Taking it one step further, using css based on this I added arrows to my back and next buttons (yes I know its not 100% cross-browser, but slick none the less).
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
margin:20px auto;
}
.triangle-down {
border-bottom:none;
border-top: 100px solid red;
}
.triangle-left {
border-left:none;
border-right: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-right {
border-right:none;
border-left: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-after:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid red;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-after-right:after {
border-right:none;
border-left: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
.triangle-before:before {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid blue;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-before-left:before {
border-left:none;
border-right: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
<div class="triangle"></div>
<div class="triangle triangle-down"></div>
<div class="triangle triangle-left"></div>
<div class="triangle triangle-right"></div>
<a class="triangle-before triangle-before-left" href="#">Back</a>
<a class="triangle-after triangle-after-right" href="#">Next</a>
CSS clip-path
This is something I feel this question has missed; clip-path
clip-path in a nutshell
Clipping, with the clip-path property, is akin to cutting a shape (like a circle or a pentagon) from a rectangular piece of paper. The property belongs to the “CSS Masking Module Level 1” specification. The spec states, “CSS masking provides two means for partially or fully hiding portions of visual elements: masking and clipping”.
Extract from Smashing Magazine
clip-path will use the element itself rather than its borders to cut the shape you specify in its parameters. It uses a super simple percentage based co-ordinate system which makes editing it very easy and means you can pick it up and create weird and wonderful shapes in a matter of minutes.
Triangle Shape Example
div {
-webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
background: red;
width: 100px;
height: 100px;
}
<div></div>
Downside
It does have a major downside at the moment, one being it's major lack of support, only really being covered within -webkit- browsers and having no support on IE and only very partial in FireFox.
Resources
Here are some useful resources and material to help better understand clip-path and also start creating your own.
Clippy - A clip-path generator
The W3C Candidate Recommendation File
MDN clip-path documentation
clip-path Browser Support
Different approach. With linear gradient (for IE, only IE 10+).
You can use any angle:
.triangle {
margin: 50px auto;
width: 100px;
height: 100px;
/* linear gradient */
background: -moz-linear-gradient(-45deg, rgba(255,0,0,0) 0%, rgba(255,0,0,0) 50%, rgba(255,0,0,1) 50%, rgba(255,0,0,1) 100%);
/* FF3.6+ */
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,1)), color-stop(100%,rgba(255,0,0,1)));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Opera 11.10+ */
background: -ms-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* IE10+ */
background: linear-gradient(135deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* W3C */;
}
<div class="triangle"></div>
Here is jsfiddle
OK, this triangle will get created because of the way that borders of the elements work together in HTML and CSS...
As we usually use 1 or 2px borders, we never notice that borders make a 45° angles to each others with the same width and if the width changes, the angle degree get changed as well, run the CSS code I created below:
.triangle {
width: 100px;
height: 100px;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
Then in the next step, we don't have any width or height, something like this:
.triangle {
width: 0;
height: 0;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
And now we make the left and right borders invisible to make our desirable triangle as below:
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="triangle"></div>
If you not willing to run the snippet to see the steps, I've created an image sequence to have a look at all steps in one image:
This is an old question, but I think will worth it to share how to create an arrow using this triangle technique.
Step 1:
Lets create 2 triangles, for the second one we will use the :after pseudo class and position it just below the other:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #ccc;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Step 2
Now we just have to set the predominant border color of the second triangle to the same color of the background:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #fff;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Fiddle with all the arrows:
http://jsfiddle.net/tomsarduy/r0zksgeu/
If you want to apply border to the triangle read this: Create a triangle with CSS?
Almost all the answers focus on the triangle built using border so I am going to elaborate the linear-gradient method (as started in the answer of #lima_fil).
Using a degree value like 45° will force us to respect a specific ratio of height/width in order to obtain the triangle we want and this won't be responsive:
.tri {
width:100px;
height:100px;
background:linear-gradient(45deg, transparent 49.5%,red 50%);
/*To illustrate*/
border:1px solid;
}
Good one
<div class="tri"></div>
bad one
<div class="tri" style="width:150px"></div>
bad one
<div class="tri" style="height:30px"></div>
Instead of doing this we should consider predefined values of direction like to bottom, to top, etc. In this case we can obtain any kind of triangle shape while keeping it responsive.
1) Rectangle triangle
To obtain such triangle we need one linear-gradient and a diagonal direction like to bottom right, to top left, to bottom left, etc
.tri-1,.tri-2 {
display:inline-block;
width:100px;
height:100px;
background:linear-gradient(to bottom left, transparent 49.5%,red 50%);
border:1px solid;
animation:change 2s linear infinite alternate;
}
.tri-2 {
background:linear-gradient(to top right, transparent 49.5%,red 50%);
border:none;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri-1"></div>
<div class="tri-2"></div>
2) isosceles triangle
For this one we will need 2 linear-gradient like above and each one will take half the width (or the height). It's like we create a mirror image of the first triangle.
.tri {
display:inline-block;
width:100px;
height:100px;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:50.3% 100%; /* I use a value slightly bigger than 50% to avoid having a small gap between both gradient*/
background-position:left,right;
background-repeat:no-repeat;
animation:change 2s linear infinite alternate;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri"></div>
3) equilateral triangle
This one is a bit tricky to handle as we need to keep a relation between the height and width of the gradient. We will have the same triangle as above but we will make the calculation more complex in order to transform the isosceles triangle to an equilateral one.
To make it easy, we will consider that the width of our div is known and the height is big enough to be able to draw our triangle inside (height >= width).
We have our two gradient g1 and g2, the blue line is the width of the div w and each gradient will have 50% of it (w/2) and each side of the triangle sould be equal to w. The green line is the height of both gradient hg and we can easily obtain the formula below:
(w/2)² + hg² = w² ---> hg = (sqrt(3)/2) * w ---> hg = 0.866 * w
We can rely on calc() in order to do our calculation and to obtain the needed result:
.tri {
--w:100px;
width:var(--w);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:calc(var(--w)/2 + 0.5px) calc(0.866 * var(--w));
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
Another way is to control the height of div and keep the syntax of gradient easy:
.tri {
--w:100px;
width:var(--w);
height:calc(0.866 * var(--w));
display:inline-block;
background:
linear-gradient(to bottom right, transparent 49.8%,red 50%) left,
linear-gradient(to bottom left, transparent 49.8%,red 50%) right;
background-size:50.2% 100%;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
4) Random triangle
To obtain a random triangle, it's easy as we simply need to remove the condition of 50% of each one BUT we should keep two condition (both should have the same height and the sum of both width should be 100%).
.tri-1 {
width:100px;
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 50%,red 0),
linear-gradient(to bottom left, transparent 50%,red 0);
background-size:20% 60%,80% 60%;
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri-1"></div>
But what if we want to define a value for each side? We simply need to do calculation again!
Let's define hg1 and hg2 as the height of our gradient (both are equal to the red line) then wg1 and wg2 as the width of our gradient (wg1 + wg2 = a). I will not going to detail the calculation but at then end we will have:
wg2 = (a²+c²-b²)/(2a)
wg1 = a - wg2
hg1 = hg2 = sqrt(b² - wg1²) = sqrt(c² - wg2²)
Now we have reached the limit of CSS as even with calc() we won't be able to implement this so we simply need to gather the final result manually and use them as fixed size:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2));
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
Bonus
We should not forget that we can also apply rotation and/or skew and we have more option to obtain more triangle:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2) - 0.5px);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49%,red 50%),
linear-gradient(to bottom left, transparent 49%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="transform:skewY(25deg)"></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;transform:rotate(20deg)" ></div>
And of course we should keep in mind the SVG solution which can be more suitable in some situation:
svg {
width:100px;
height:100px;
}
polygon {
fill:red;
}
<svg viewBox="0 0 100 100"><polygon points="0,100 0,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,23 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="20,60 50,43 80,100" /></svg>
SASS (SCSS) triangle mixin
I wrote this to make it easier (and DRY) to automatically generate a CSS triangle:
// Triangle helper mixin (by Yair Even-Or)
// #param {Direction} $direction - either `top`, `right`, `bottom` or `left`
// #param {Color} $color [currentcolor] - Triangle color
// #param {Length} $size [1em] - Triangle size
#mixin triangle($direction, $color: currentcolor, $size: 1em) {
$size: $size/2;
$transparent: rgba($color, 0);
$opposite: (top:bottom, right:left, left:right, bottom:top);
content: '';
display: inline-block;
width: 0;
height: 0;
border: $size solid $transparent;
border-#{map-get($opposite, $direction)}-color: $color;
margin-#{$direction}: -$size;
}
use-case example:
span {
#include triangle(bottom, red, 10px);
}
Playground page
Important note: if the triangle seems pixelated in some browsers, try one of the methods described here.
If you want to play around with border-size, width and height and see how those can create different shapes, try this:
const sizes = [32, 32, 32, 32];
const triangle = document.getElementById('triangle');
function update({ target }) {
let index = null;
if (target) {
index = parseInt(target.id);
if (!isNaN(index)) {
sizes[index] = target.value;
}
}
window.requestAnimationFrame(() => {
triangle.style.borderWidth = sizes.map(size => `${ size }px`).join(' ');
if (isNaN(index)) {
triangle.style[target.id] = `${ target.value }px`;
}
});
}
document.querySelectorAll('input').forEach(input => {
input.oninput = update;
});
update({});
body {
margin: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
#triangle {
border-style: solid;
border-color: yellow magenta blue black;
background: cyan;
height: 0px;
width: 0px;
}
#controls {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
display: flex;
box-shadow: 0 0 32px rgba(0, 0, 0, .125);
}
#controls > div {
position: relative;
width: 25%;
padding: 8px;
box-sizing: border-box;
display: flex;
}
input {
margin: 0;
width: 100%;
position: relative;
}
<div id="triangle" style="border-width: 32px 32px 32px 32px;"></div>
<div id="controls">
<div><input type="range" min="0" max="128" value="32" id="0" /></div>
<div><input type="range" min="0" max="128" value="32" id="1" /></div>
<div><input type="range" min="0" max="128" value="32" id="2" /></div>
<div><input type="range" min="0" max="128" value="32" id="3" /></div>
<div><input type="range" min="0" max="128" value="0" id="width" /></div>
<div><input type="range" min="0" max="128" value="0" id="height" /></div>
</div>
here is another fiddle:
.container:after {
position: absolute;
right: 0;
content: "";
margin-right:-50px;
margin-bottom: -8px;
border-width: 25px;
border-style: solid;
border-color: transparent transparent transparent #000;
width: 0;
height: 0;
z-index: 10;
-webkit-transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
bottom: 21px;
}
.container {
float: left;
margin-top: 100px;
position: relative;
width: 150px;
height: 80px;
background-color: #000;
}
.containerRed {
float: left;
margin-top: 100px;
position: relative;
width: 100px;
height: 80px;
background-color: red;
}
https://jsfiddle.net/qdhvdb17/
Others have already explained this well. Let me give you an animation which will explain this quickly: http://codepen.io/chriscoyier/pen/lotjh
Here is some code for you to play with and learn the concepts.
HTML:
<html>
<body>
<div id="border-demo">
</div>
</body>
</html>
CSS:
/*border-width is border thickness*/
#border-demo {
background: gray;
border-color: yellow blue red green;/*top right bottom left*/
border-style: solid;
border-width: 25px 25px 25px 25px;/*top right bottom left*/
height: 50px;
width: 50px;
}
Play with this and see what happens. Set height and width to zero. Then remove top border and make left and right transparent, or just look at the code below to make a css triangle:
#border-demo {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid blue;
}
I know this is an old one, but I'd like to add to this discussion that There are at least 5 different methods for creating a triangle using HTML & CSS alone.
Using borders
Using linear-gradient
Using conic-gradient
Using
transform and overflow
Using clip-path
I think that all have been covered here except for method 3, using the conic-gradient, so I will share it here:
.triangle{
width: 40px;
height: 40px;
background: conic-gradient(at 50% 50%,transparent 135deg,green 0,green 225deg, transparent 0);
}
<div class="triangle"></div>
use clip-path: polygon(50% 0%, 100% 100%, 0% 100%); for creating easy to Triangle
<div class="triangle"></div>
.triangle{width:200px; height:200px;background:#000;clip-path: polygon(50% 0%, 100% 100%, 0% 100%);}
After reading through the other answers here I see there are great explanations as to why the CSS triangle works the way it does. I would consider it to be somewhat of a trick, versus something that you could apply generically.
For something that's easier to read and maintain, I would recommend you define your geometry in SVG.
Then you can convert that SVG using data uri by adding the data:image/svg+xml, prefix. As a data uri, it can now be used as a background-image in a CSS. Because the SVG is in clear text, you can readily make updates to the geometry, stroke, and fill color.
div.tri {
width: 100px;
height: 100px;
display: inline-block;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="red" d="M31.345 29H1.655L16.5 1.96z"/></svg>');
}
<div>
<div class="tri"></div>
<div class="tri"></div>
<div class="tri"></div>
</div>
Try This:-
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
clip-path has the best result for me - works great for divs/containers with and without fixed dimensions:
.triangleContainer{
position: relative;
width: 500px;
height: 500px;
}
.triangleContainer::before{
content: "";
position: absolute;
background:blue;
top: 0;
left: 0;
width: 100%;
height: 100%;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
}

Having one thicker border does no display correctly [duplicate]

There're plenty of different CSS shapes over at CSS Tricks - Shapes of CSS and I'm particularly puzzled with a triangle:
#triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div id="triangle-up"></div>
How and why does it work?
CSS Triangles: A Tragedy in Five Acts
As alex said, borders of equal width butt up against each other at 45 degree angles:
When you have no top border, it looks like this:
Then you give it a width of 0...
...and a height of 0...
...and finally, you make the two side borders transparent:
That results in a triangle.
The borders use an angled edge where they intersect (45° angle with equal width borders, but changing the border widths can skew the angle).
div {
width: 60px;
border-width: 30px;
border-color: red blue green yellow;
border-style: solid;
}
<div></div>
Have a look to the jsFiddle.
By hiding certain borders, you can get the triangle effect (as you can see above by making the different portions different colours). transparent is often used as an edge colour to achieve the triangle shape.
Start with a basic square and borders. Each border will be given a different color so we can tell them apart:
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 200px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
which gives you this:
But there's no need for the top border, so set its width to 0px. Now our border-bottom of 200px will make our triangle 200px tall.
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
and we will get this:
Then to hide the two side triangles, set the border-color to transparent. Since the top-border has been effectively deleted, we can set the border-top-color to transparent as well.
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
finally we get this:
Different approach:
CSS3 triangles with transform rotate
Triangular shape is pretty easy to make using this technique. For people who prefer to see an animation explaining how this technique works here it is :
Link to the ANIMATION : How to make a CSS3 triangle.
And DEMO : CSS3 triangles made with transform rotate.
Otherwise, here is detailed explanation in 4 acts (this is not a tragedy) of how to make an isosceles right-angled triangle with one element.
Note 1 : for non isosceles triangles and fancy stuff, you can see step 4.
Note 2 : in the following snippets, the vendor prefixes aren't included. they are included in the codepen demos.
Note 3 : the HTML for the following explanation is always : <div class="tr"></div>
STEP 1 : Make a div
Easy, just make sure that width = 1.41 x height. You may use any techinque (see here) including the use of percentages and padding-bottom to maintain the aspect ratio and make a responsive triangle. In the following image, the div has a golden yellow border.
In that div, insert a pseudo element and give it 100% width and height of parent. The pseudo element has a blue background in the following image.
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr: before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
}
STEP 2 : Let's rotate
First, most important : define a transform origin. The default origin is in the center of the pseudo element and we need it at the bottom left. By adding this CSS to the pseudo element :
transform-origin:0 100%; or transform-origin: left bottom;
Now we can rotate the pseudo element 45 degrees clockwise with transform : rotate(45deg);
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 3 : hide it
To hide the unwanted parts of the pseudo element (everything that overflows the div with the yellow border) you just need to set overflow:hidden; on the container. after removing the yellow border, you get... a TRIANGLE! :
DEMO
CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
overflow: hidden;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 4 : go further...
As shown in the demo, you can customize the triangles :
Make them thinner or flatter by playing with skewX().
Make them point left, right or any other direction by playing with the transform origin and rotation direction.
Make some reflexion with 3D transform property.
Give the triangle borders
Put an image inside the triangle
Much more... Unleash the powers of CSS3!
Why use this technique?
Triangle can easily be responsive.
You can make a triangle with border.
You can maintain the boundaries of the triangle. This means that you can trigger the hover state or click event only when the cursor is inside the triangle. This can become very handy in some situations like this one where each triangle can't overlay its neighbours so each triangle has its own hover state.
You can make some fancy effects like reflections.
It will help you understand 2d and 3d transform properties.
Why not use this technique?
The main drawback is the browser compatibility, the 2d transform properties are supported by IE9+ and therefore you can't use this technique if you plan on supporting IE8. See CanIuse for more info. For some fancy effects using 3d transforms like the reflection browser support is IE10+ (see canIuse for more info).
You don't need anything responsive and a plain triangle is fine for you then you should go for the border technique explained here : better browser compatibility and easier to understand thanks to the amazing posts here.
Here is an animation in JSFiddle I created for demonstration.
Also see snippet below.
This is an Animated GIF made from a Screencast
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0', 'margin-top': '120'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 20px 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Random version
/**
* Randomize array element order in-place.
* Using Durstenfeld shuffle algorithm.
*/
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
transforms = shuffleArray(transforms)
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
All at once version
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
$(this)
.animate({'border-top-width': 0 ,
'border-left-width': 30 ,
'border-right-width': 30 ,
'border-bottom-width': 80 ,
'width': 0 ,
'height': 0 ,
'margin-left': 100,
'margin-top': 150,
'borderTopColor': 'transparent',
'borderRightColor': 'transparent',
'borderLeftColor': 'transparent'}, duration)
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Lets say we have the following div:
<div id="triangle" />
Now Edit the CSS step-by-step, so you will get clear idea what is happening around
STEP 1:
JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid black ;
border-right: 50px solid black;
border-bottom: 50px solid black;
border-top: 50px solid black;
}
This is a simple div. With a very simple CSS. So a layman can understand. Div has dimensions 150 x 150 pixels with the border 50 pixels. The image is attached:
STEP 2: JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the border-color of all 4 sides. The image is attached.
STEP:3 JSfiddle Link:
#triangle {
background: purple;
width :0;
height:0;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the height & width of div from 150 pixels to zero. The image is attached
STEP 4: JSfiddle:
#triangle {
background: purple;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I have made all the borders transparent apart from the bottom border. The image is attached below.
STEP 5: JSfiddle Link:
#triangle {
background: white;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I just changed the background color to white. The image is attached.
Hence we got the triangle we needed.
And now something completely different...
Instead of using css tricks don't forget about solutions as simple as html entities:
▲
Result:
▲
See: What are the HTML entities for up and down triangles?
Consider the below triangle
.triangle {
border-bottom:15px solid #000;
border-left:10px solid transparent;
border-right:10px solid transparent;
width:0;
height:0;
}
This is what we are given:
Why it came out in this shape? The below diagram explains the dimensions, note that 15px was used for the bottom border and 10px was used for left and right.
It's pretty easy to make a right-angle triangle also by removing the right border.
Taking it one step further, using css based on this I added arrows to my back and next buttons (yes I know its not 100% cross-browser, but slick none the less).
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
margin:20px auto;
}
.triangle-down {
border-bottom:none;
border-top: 100px solid red;
}
.triangle-left {
border-left:none;
border-right: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-right {
border-right:none;
border-left: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-after:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid red;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-after-right:after {
border-right:none;
border-left: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
.triangle-before:before {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid blue;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-before-left:before {
border-left:none;
border-right: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
<div class="triangle"></div>
<div class="triangle triangle-down"></div>
<div class="triangle triangle-left"></div>
<div class="triangle triangle-right"></div>
<a class="triangle-before triangle-before-left" href="#">Back</a>
<a class="triangle-after triangle-after-right" href="#">Next</a>
CSS clip-path
This is something I feel this question has missed; clip-path
clip-path in a nutshell
Clipping, with the clip-path property, is akin to cutting a shape (like a circle or a pentagon) from a rectangular piece of paper. The property belongs to the “CSS Masking Module Level 1” specification. The spec states, “CSS masking provides two means for partially or fully hiding portions of visual elements: masking and clipping”.
Extract from Smashing Magazine
clip-path will use the element itself rather than its borders to cut the shape you specify in its parameters. It uses a super simple percentage based co-ordinate system which makes editing it very easy and means you can pick it up and create weird and wonderful shapes in a matter of minutes.
Triangle Shape Example
div {
-webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
background: red;
width: 100px;
height: 100px;
}
<div></div>
Downside
It does have a major downside at the moment, one being it's major lack of support, only really being covered within -webkit- browsers and having no support on IE and only very partial in FireFox.
Resources
Here are some useful resources and material to help better understand clip-path and also start creating your own.
Clippy - A clip-path generator
The W3C Candidate Recommendation File
MDN clip-path documentation
clip-path Browser Support
Different approach. With linear gradient (for IE, only IE 10+).
You can use any angle:
.triangle {
margin: 50px auto;
width: 100px;
height: 100px;
/* linear gradient */
background: -moz-linear-gradient(-45deg, rgba(255,0,0,0) 0%, rgba(255,0,0,0) 50%, rgba(255,0,0,1) 50%, rgba(255,0,0,1) 100%);
/* FF3.6+ */
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,1)), color-stop(100%,rgba(255,0,0,1)));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Opera 11.10+ */
background: -ms-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* IE10+ */
background: linear-gradient(135deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* W3C */;
}
<div class="triangle"></div>
Here is jsfiddle
OK, this triangle will get created because of the way that borders of the elements work together in HTML and CSS...
As we usually use 1 or 2px borders, we never notice that borders make a 45° angles to each others with the same width and if the width changes, the angle degree get changed as well, run the CSS code I created below:
.triangle {
width: 100px;
height: 100px;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
Then in the next step, we don't have any width or height, something like this:
.triangle {
width: 0;
height: 0;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
And now we make the left and right borders invisible to make our desirable triangle as below:
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="triangle"></div>
If you not willing to run the snippet to see the steps, I've created an image sequence to have a look at all steps in one image:
This is an old question, but I think will worth it to share how to create an arrow using this triangle technique.
Step 1:
Lets create 2 triangles, for the second one we will use the :after pseudo class and position it just below the other:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #ccc;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Step 2
Now we just have to set the predominant border color of the second triangle to the same color of the background:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #fff;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Fiddle with all the arrows:
http://jsfiddle.net/tomsarduy/r0zksgeu/
If you want to apply border to the triangle read this: Create a triangle with CSS?
Almost all the answers focus on the triangle built using border so I am going to elaborate the linear-gradient method (as started in the answer of #lima_fil).
Using a degree value like 45° will force us to respect a specific ratio of height/width in order to obtain the triangle we want and this won't be responsive:
.tri {
width:100px;
height:100px;
background:linear-gradient(45deg, transparent 49.5%,red 50%);
/*To illustrate*/
border:1px solid;
}
Good one
<div class="tri"></div>
bad one
<div class="tri" style="width:150px"></div>
bad one
<div class="tri" style="height:30px"></div>
Instead of doing this we should consider predefined values of direction like to bottom, to top, etc. In this case we can obtain any kind of triangle shape while keeping it responsive.
1) Rectangle triangle
To obtain such triangle we need one linear-gradient and a diagonal direction like to bottom right, to top left, to bottom left, etc
.tri-1,.tri-2 {
display:inline-block;
width:100px;
height:100px;
background:linear-gradient(to bottom left, transparent 49.5%,red 50%);
border:1px solid;
animation:change 2s linear infinite alternate;
}
.tri-2 {
background:linear-gradient(to top right, transparent 49.5%,red 50%);
border:none;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri-1"></div>
<div class="tri-2"></div>
2) isosceles triangle
For this one we will need 2 linear-gradient like above and each one will take half the width (or the height). It's like we create a mirror image of the first triangle.
.tri {
display:inline-block;
width:100px;
height:100px;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:50.3% 100%; /* I use a value slightly bigger than 50% to avoid having a small gap between both gradient*/
background-position:left,right;
background-repeat:no-repeat;
animation:change 2s linear infinite alternate;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri"></div>
3) equilateral triangle
This one is a bit tricky to handle as we need to keep a relation between the height and width of the gradient. We will have the same triangle as above but we will make the calculation more complex in order to transform the isosceles triangle to an equilateral one.
To make it easy, we will consider that the width of our div is known and the height is big enough to be able to draw our triangle inside (height >= width).
We have our two gradient g1 and g2, the blue line is the width of the div w and each gradient will have 50% of it (w/2) and each side of the triangle sould be equal to w. The green line is the height of both gradient hg and we can easily obtain the formula below:
(w/2)² + hg² = w² ---> hg = (sqrt(3)/2) * w ---> hg = 0.866 * w
We can rely on calc() in order to do our calculation and to obtain the needed result:
.tri {
--w:100px;
width:var(--w);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:calc(var(--w)/2 + 0.5px) calc(0.866 * var(--w));
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
Another way is to control the height of div and keep the syntax of gradient easy:
.tri {
--w:100px;
width:var(--w);
height:calc(0.866 * var(--w));
display:inline-block;
background:
linear-gradient(to bottom right, transparent 49.8%,red 50%) left,
linear-gradient(to bottom left, transparent 49.8%,red 50%) right;
background-size:50.2% 100%;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
4) Random triangle
To obtain a random triangle, it's easy as we simply need to remove the condition of 50% of each one BUT we should keep two condition (both should have the same height and the sum of both width should be 100%).
.tri-1 {
width:100px;
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 50%,red 0),
linear-gradient(to bottom left, transparent 50%,red 0);
background-size:20% 60%,80% 60%;
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri-1"></div>
But what if we want to define a value for each side? We simply need to do calculation again!
Let's define hg1 and hg2 as the height of our gradient (both are equal to the red line) then wg1 and wg2 as the width of our gradient (wg1 + wg2 = a). I will not going to detail the calculation but at then end we will have:
wg2 = (a²+c²-b²)/(2a)
wg1 = a - wg2
hg1 = hg2 = sqrt(b² - wg1²) = sqrt(c² - wg2²)
Now we have reached the limit of CSS as even with calc() we won't be able to implement this so we simply need to gather the final result manually and use them as fixed size:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2));
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
Bonus
We should not forget that we can also apply rotation and/or skew and we have more option to obtain more triangle:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2) - 0.5px);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49%,red 50%),
linear-gradient(to bottom left, transparent 49%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="transform:skewY(25deg)"></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;transform:rotate(20deg)" ></div>
And of course we should keep in mind the SVG solution which can be more suitable in some situation:
svg {
width:100px;
height:100px;
}
polygon {
fill:red;
}
<svg viewBox="0 0 100 100"><polygon points="0,100 0,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,23 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="20,60 50,43 80,100" /></svg>
SASS (SCSS) triangle mixin
I wrote this to make it easier (and DRY) to automatically generate a CSS triangle:
// Triangle helper mixin (by Yair Even-Or)
// #param {Direction} $direction - either `top`, `right`, `bottom` or `left`
// #param {Color} $color [currentcolor] - Triangle color
// #param {Length} $size [1em] - Triangle size
#mixin triangle($direction, $color: currentcolor, $size: 1em) {
$size: $size/2;
$transparent: rgba($color, 0);
$opposite: (top:bottom, right:left, left:right, bottom:top);
content: '';
display: inline-block;
width: 0;
height: 0;
border: $size solid $transparent;
border-#{map-get($opposite, $direction)}-color: $color;
margin-#{$direction}: -$size;
}
use-case example:
span {
#include triangle(bottom, red, 10px);
}
Playground page
Important note: if the triangle seems pixelated in some browsers, try one of the methods described here.
If you want to play around with border-size, width and height and see how those can create different shapes, try this:
const sizes = [32, 32, 32, 32];
const triangle = document.getElementById('triangle');
function update({ target }) {
let index = null;
if (target) {
index = parseInt(target.id);
if (!isNaN(index)) {
sizes[index] = target.value;
}
}
window.requestAnimationFrame(() => {
triangle.style.borderWidth = sizes.map(size => `${ size }px`).join(' ');
if (isNaN(index)) {
triangle.style[target.id] = `${ target.value }px`;
}
});
}
document.querySelectorAll('input').forEach(input => {
input.oninput = update;
});
update({});
body {
margin: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
#triangle {
border-style: solid;
border-color: yellow magenta blue black;
background: cyan;
height: 0px;
width: 0px;
}
#controls {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
display: flex;
box-shadow: 0 0 32px rgba(0, 0, 0, .125);
}
#controls > div {
position: relative;
width: 25%;
padding: 8px;
box-sizing: border-box;
display: flex;
}
input {
margin: 0;
width: 100%;
position: relative;
}
<div id="triangle" style="border-width: 32px 32px 32px 32px;"></div>
<div id="controls">
<div><input type="range" min="0" max="128" value="32" id="0" /></div>
<div><input type="range" min="0" max="128" value="32" id="1" /></div>
<div><input type="range" min="0" max="128" value="32" id="2" /></div>
<div><input type="range" min="0" max="128" value="32" id="3" /></div>
<div><input type="range" min="0" max="128" value="0" id="width" /></div>
<div><input type="range" min="0" max="128" value="0" id="height" /></div>
</div>
here is another fiddle:
.container:after {
position: absolute;
right: 0;
content: "";
margin-right:-50px;
margin-bottom: -8px;
border-width: 25px;
border-style: solid;
border-color: transparent transparent transparent #000;
width: 0;
height: 0;
z-index: 10;
-webkit-transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
bottom: 21px;
}
.container {
float: left;
margin-top: 100px;
position: relative;
width: 150px;
height: 80px;
background-color: #000;
}
.containerRed {
float: left;
margin-top: 100px;
position: relative;
width: 100px;
height: 80px;
background-color: red;
}
https://jsfiddle.net/qdhvdb17/
Others have already explained this well. Let me give you an animation which will explain this quickly: http://codepen.io/chriscoyier/pen/lotjh
Here is some code for you to play with and learn the concepts.
HTML:
<html>
<body>
<div id="border-demo">
</div>
</body>
</html>
CSS:
/*border-width is border thickness*/
#border-demo {
background: gray;
border-color: yellow blue red green;/*top right bottom left*/
border-style: solid;
border-width: 25px 25px 25px 25px;/*top right bottom left*/
height: 50px;
width: 50px;
}
Play with this and see what happens. Set height and width to zero. Then remove top border and make left and right transparent, or just look at the code below to make a css triangle:
#border-demo {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid blue;
}
I know this is an old one, but I'd like to add to this discussion that There are at least 5 different methods for creating a triangle using HTML & CSS alone.
Using borders
Using linear-gradient
Using conic-gradient
Using
transform and overflow
Using clip-path
I think that all have been covered here except for method 3, using the conic-gradient, so I will share it here:
.triangle{
width: 40px;
height: 40px;
background: conic-gradient(at 50% 50%,transparent 135deg,green 0,green 225deg, transparent 0);
}
<div class="triangle"></div>
use clip-path: polygon(50% 0%, 100% 100%, 0% 100%); for creating easy to Triangle
<div class="triangle"></div>
.triangle{width:200px; height:200px;background:#000;clip-path: polygon(50% 0%, 100% 100%, 0% 100%);}
After reading through the other answers here I see there are great explanations as to why the CSS triangle works the way it does. I would consider it to be somewhat of a trick, versus something that you could apply generically.
For something that's easier to read and maintain, I would recommend you define your geometry in SVG.
Then you can convert that SVG using data uri by adding the data:image/svg+xml, prefix. As a data uri, it can now be used as a background-image in a CSS. Because the SVG is in clear text, you can readily make updates to the geometry, stroke, and fill color.
div.tri {
width: 100px;
height: 100px;
display: inline-block;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="red" d="M31.345 29H1.655L16.5 1.96z"/></svg>');
}
<div>
<div class="tri"></div>
<div class="tri"></div>
<div class="tri"></div>
</div>
Try This:-
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
clip-path has the best result for me - works great for divs/containers with and without fixed dimensions:
.triangleContainer{
position: relative;
width: 500px;
height: 500px;
}
.triangleContainer::before{
content: "";
position: absolute;
background:blue;
top: 0;
left: 0;
width: 100%;
height: 100%;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
}

How do I use gradient image which gradates in both directions as border-image?

I want my <div> to have a bottom border which starts from a distance away from the left. It's like:
abc
^^^^^^^^^^
where ^ stands for a piece of border.
I achieved this using border-image. I set a border-image to a linear-gradient() image, which starts transparent, and becomes gray from some pixels.
<style>
div {
width: 200px;
border-top-style: none;
border-bottom-style: solid;
border-width: 1px;
border-image: linear-gradient(to right,
transparent 0,
transparent 1em,
lightgray 1em,
lightgray 100%) 100% 1;
}
</style>
<div>abc</div>
Now the new requirement is to add a 1px white line right below the existing line to mimic a 3d effect. I thought I could simply add a vertical gradient to the border image, but I don't know how to do it.
Instead of border consider multiple background. I used different colors to better see the result:
.box {
width: 200px;
background:
linear-gradient(blue, blue) 1em 100%/ 100% 1px no-repeat,
linear-gradient(red, red) 1em 100%/ 100% 2px no-repeat;
}
<div class="box">abc</div>
You can Achive it with box-shadow
If you are using display: flex to your div you should position pseudo after element using position: absoute
See this example:
body {
background-color: lightgreen;
}
div {
display: flex;
position: relative;
}
div:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
display: block;
width: 200px;
height: 1px;
box-shadow: 10px 1px 0 0 lightgray, 10px 2px 0 0 white;
}
<div>abc</div>
<div>edf</div>

Arrow before and after lines CSS [duplicate]

There're plenty of different CSS shapes over at CSS Tricks - Shapes of CSS and I'm particularly puzzled with a triangle:
#triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div id="triangle-up"></div>
How and why does it work?
CSS Triangles: A Tragedy in Five Acts
As alex said, borders of equal width butt up against each other at 45 degree angles:
When you have no top border, it looks like this:
Then you give it a width of 0...
...and a height of 0...
...and finally, you make the two side borders transparent:
That results in a triangle.
The borders use an angled edge where they intersect (45° angle with equal width borders, but changing the border widths can skew the angle).
div {
width: 60px;
border-width: 30px;
border-color: red blue green yellow;
border-style: solid;
}
<div></div>
Have a look to the jsFiddle.
By hiding certain borders, you can get the triangle effect (as you can see above by making the different portions different colours). transparent is often used as an edge colour to achieve the triangle shape.
Start with a basic square and borders. Each border will be given a different color so we can tell them apart:
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 200px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
which gives you this:
But there's no need for the top border, so set its width to 0px. Now our border-bottom of 200px will make our triangle 200px tall.
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
and we will get this:
Then to hide the two side triangles, set the border-color to transparent. Since the top-border has been effectively deleted, we can set the border-top-color to transparent as well.
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
finally we get this:
Different approach:
CSS3 triangles with transform rotate
Triangular shape is pretty easy to make using this technique. For people who prefer to see an animation explaining how this technique works here it is :
Link to the ANIMATION : How to make a CSS3 triangle.
And DEMO : CSS3 triangles made with transform rotate.
Otherwise, here is detailed explanation in 4 acts (this is not a tragedy) of how to make an isosceles right-angled triangle with one element.
Note 1 : for non isosceles triangles and fancy stuff, you can see step 4.
Note 2 : in the following snippets, the vendor prefixes aren't included. they are included in the codepen demos.
Note 3 : the HTML for the following explanation is always : <div class="tr"></div>
STEP 1 : Make a div
Easy, just make sure that width = 1.41 x height. You may use any techinque (see here) including the use of percentages and padding-bottom to maintain the aspect ratio and make a responsive triangle. In the following image, the div has a golden yellow border.
In that div, insert a pseudo element and give it 100% width and height of parent. The pseudo element has a blue background in the following image.
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr: before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
}
STEP 2 : Let's rotate
First, most important : define a transform origin. The default origin is in the center of the pseudo element and we need it at the bottom left. By adding this CSS to the pseudo element :
transform-origin:0 100%; or transform-origin: left bottom;
Now we can rotate the pseudo element 45 degrees clockwise with transform : rotate(45deg);
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 3 : hide it
To hide the unwanted parts of the pseudo element (everything that overflows the div with the yellow border) you just need to set overflow:hidden; on the container. after removing the yellow border, you get... a TRIANGLE! :
DEMO
CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
overflow: hidden;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 4 : go further...
As shown in the demo, you can customize the triangles :
Make them thinner or flatter by playing with skewX().
Make them point left, right or any other direction by playing with the transform origin and rotation direction.
Make some reflexion with 3D transform property.
Give the triangle borders
Put an image inside the triangle
Much more... Unleash the powers of CSS3!
Why use this technique?
Triangle can easily be responsive.
You can make a triangle with border.
You can maintain the boundaries of the triangle. This means that you can trigger the hover state or click event only when the cursor is inside the triangle. This can become very handy in some situations like this one where each triangle can't overlay its neighbours so each triangle has its own hover state.
You can make some fancy effects like reflections.
It will help you understand 2d and 3d transform properties.
Why not use this technique?
The main drawback is the browser compatibility, the 2d transform properties are supported by IE9+ and therefore you can't use this technique if you plan on supporting IE8. See CanIuse for more info. For some fancy effects using 3d transforms like the reflection browser support is IE10+ (see canIuse for more info).
You don't need anything responsive and a plain triangle is fine for you then you should go for the border technique explained here : better browser compatibility and easier to understand thanks to the amazing posts here.
Here is an animation in JSFiddle I created for demonstration.
Also see snippet below.
This is an Animated GIF made from a Screencast
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0', 'margin-top': '120'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 20px 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Random version
/**
* Randomize array element order in-place.
* Using Durstenfeld shuffle algorithm.
*/
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
transforms = shuffleArray(transforms)
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
All at once version
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
$(this)
.animate({'border-top-width': 0 ,
'border-left-width': 30 ,
'border-right-width': 30 ,
'border-bottom-width': 80 ,
'width': 0 ,
'height': 0 ,
'margin-left': 100,
'margin-top': 150,
'borderTopColor': 'transparent',
'borderRightColor': 'transparent',
'borderLeftColor': 'transparent'}, duration)
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Lets say we have the following div:
<div id="triangle" />
Now Edit the CSS step-by-step, so you will get clear idea what is happening around
STEP 1:
JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid black ;
border-right: 50px solid black;
border-bottom: 50px solid black;
border-top: 50px solid black;
}
This is a simple div. With a very simple CSS. So a layman can understand. Div has dimensions 150 x 150 pixels with the border 50 pixels. The image is attached:
STEP 2: JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the border-color of all 4 sides. The image is attached.
STEP:3 JSfiddle Link:
#triangle {
background: purple;
width :0;
height:0;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the height & width of div from 150 pixels to zero. The image is attached
STEP 4: JSfiddle:
#triangle {
background: purple;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I have made all the borders transparent apart from the bottom border. The image is attached below.
STEP 5: JSfiddle Link:
#triangle {
background: white;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I just changed the background color to white. The image is attached.
Hence we got the triangle we needed.
And now something completely different...
Instead of using css tricks don't forget about solutions as simple as html entities:
▲
Result:
▲
See: What are the HTML entities for up and down triangles?
Consider the below triangle
.triangle {
border-bottom:15px solid #000;
border-left:10px solid transparent;
border-right:10px solid transparent;
width:0;
height:0;
}
This is what we are given:
Why it came out in this shape? The below diagram explains the dimensions, note that 15px was used for the bottom border and 10px was used for left and right.
It's pretty easy to make a right-angle triangle also by removing the right border.
Taking it one step further, using css based on this I added arrows to my back and next buttons (yes I know its not 100% cross-browser, but slick none the less).
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
margin:20px auto;
}
.triangle-down {
border-bottom:none;
border-top: 100px solid red;
}
.triangle-left {
border-left:none;
border-right: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-right {
border-right:none;
border-left: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-after:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid red;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-after-right:after {
border-right:none;
border-left: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
.triangle-before:before {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid blue;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-before-left:before {
border-left:none;
border-right: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
<div class="triangle"></div>
<div class="triangle triangle-down"></div>
<div class="triangle triangle-left"></div>
<div class="triangle triangle-right"></div>
<a class="triangle-before triangle-before-left" href="#">Back</a>
<a class="triangle-after triangle-after-right" href="#">Next</a>
CSS clip-path
This is something I feel this question has missed; clip-path
clip-path in a nutshell
Clipping, with the clip-path property, is akin to cutting a shape (like a circle or a pentagon) from a rectangular piece of paper. The property belongs to the “CSS Masking Module Level 1” specification. The spec states, “CSS masking provides two means for partially or fully hiding portions of visual elements: masking and clipping”.
Extract from Smashing Magazine
clip-path will use the element itself rather than its borders to cut the shape you specify in its parameters. It uses a super simple percentage based co-ordinate system which makes editing it very easy and means you can pick it up and create weird and wonderful shapes in a matter of minutes.
Triangle Shape Example
div {
-webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
background: red;
width: 100px;
height: 100px;
}
<div></div>
Downside
It does have a major downside at the moment, one being it's major lack of support, only really being covered within -webkit- browsers and having no support on IE and only very partial in FireFox.
Resources
Here are some useful resources and material to help better understand clip-path and also start creating your own.
Clippy - A clip-path generator
The W3C Candidate Recommendation File
MDN clip-path documentation
clip-path Browser Support
Different approach. With linear gradient (for IE, only IE 10+).
You can use any angle:
.triangle {
margin: 50px auto;
width: 100px;
height: 100px;
/* linear gradient */
background: -moz-linear-gradient(-45deg, rgba(255,0,0,0) 0%, rgba(255,0,0,0) 50%, rgba(255,0,0,1) 50%, rgba(255,0,0,1) 100%);
/* FF3.6+ */
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,1)), color-stop(100%,rgba(255,0,0,1)));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Opera 11.10+ */
background: -ms-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* IE10+ */
background: linear-gradient(135deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* W3C */;
}
<div class="triangle"></div>
Here is jsfiddle
OK, this triangle will get created because of the way that borders of the elements work together in HTML and CSS...
As we usually use 1 or 2px borders, we never notice that borders make a 45° angles to each others with the same width and if the width changes, the angle degree get changed as well, run the CSS code I created below:
.triangle {
width: 100px;
height: 100px;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
Then in the next step, we don't have any width or height, something like this:
.triangle {
width: 0;
height: 0;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
And now we make the left and right borders invisible to make our desirable triangle as below:
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="triangle"></div>
If you not willing to run the snippet to see the steps, I've created an image sequence to have a look at all steps in one image:
This is an old question, but I think will worth it to share how to create an arrow using this triangle technique.
Step 1:
Lets create 2 triangles, for the second one we will use the :after pseudo class and position it just below the other:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #ccc;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Step 2
Now we just have to set the predominant border color of the second triangle to the same color of the background:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #fff;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Fiddle with all the arrows:
http://jsfiddle.net/tomsarduy/r0zksgeu/
If you want to apply border to the triangle read this: Create a triangle with CSS?
Almost all the answers focus on the triangle built using border so I am going to elaborate the linear-gradient method (as started in the answer of #lima_fil).
Using a degree value like 45° will force us to respect a specific ratio of height/width in order to obtain the triangle we want and this won't be responsive:
.tri {
width:100px;
height:100px;
background:linear-gradient(45deg, transparent 49.5%,red 50%);
/*To illustrate*/
border:1px solid;
}
Good one
<div class="tri"></div>
bad one
<div class="tri" style="width:150px"></div>
bad one
<div class="tri" style="height:30px"></div>
Instead of doing this we should consider predefined values of direction like to bottom, to top, etc. In this case we can obtain any kind of triangle shape while keeping it responsive.
1) Rectangle triangle
To obtain such triangle we need one linear-gradient and a diagonal direction like to bottom right, to top left, to bottom left, etc
.tri-1,.tri-2 {
display:inline-block;
width:100px;
height:100px;
background:linear-gradient(to bottom left, transparent 49.5%,red 50%);
border:1px solid;
animation:change 2s linear infinite alternate;
}
.tri-2 {
background:linear-gradient(to top right, transparent 49.5%,red 50%);
border:none;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri-1"></div>
<div class="tri-2"></div>
2) isosceles triangle
For this one we will need 2 linear-gradient like above and each one will take half the width (or the height). It's like we create a mirror image of the first triangle.
.tri {
display:inline-block;
width:100px;
height:100px;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:50.3% 100%; /* I use a value slightly bigger than 50% to avoid having a small gap between both gradient*/
background-position:left,right;
background-repeat:no-repeat;
animation:change 2s linear infinite alternate;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri"></div>
3) equilateral triangle
This one is a bit tricky to handle as we need to keep a relation between the height and width of the gradient. We will have the same triangle as above but we will make the calculation more complex in order to transform the isosceles triangle to an equilateral one.
To make it easy, we will consider that the width of our div is known and the height is big enough to be able to draw our triangle inside (height >= width).
We have our two gradient g1 and g2, the blue line is the width of the div w and each gradient will have 50% of it (w/2) and each side of the triangle sould be equal to w. The green line is the height of both gradient hg and we can easily obtain the formula below:
(w/2)² + hg² = w² ---> hg = (sqrt(3)/2) * w ---> hg = 0.866 * w
We can rely on calc() in order to do our calculation and to obtain the needed result:
.tri {
--w:100px;
width:var(--w);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:calc(var(--w)/2 + 0.5px) calc(0.866 * var(--w));
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
Another way is to control the height of div and keep the syntax of gradient easy:
.tri {
--w:100px;
width:var(--w);
height:calc(0.866 * var(--w));
display:inline-block;
background:
linear-gradient(to bottom right, transparent 49.8%,red 50%) left,
linear-gradient(to bottom left, transparent 49.8%,red 50%) right;
background-size:50.2% 100%;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
4) Random triangle
To obtain a random triangle, it's easy as we simply need to remove the condition of 50% of each one BUT we should keep two condition (both should have the same height and the sum of both width should be 100%).
.tri-1 {
width:100px;
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 50%,red 0),
linear-gradient(to bottom left, transparent 50%,red 0);
background-size:20% 60%,80% 60%;
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri-1"></div>
But what if we want to define a value for each side? We simply need to do calculation again!
Let's define hg1 and hg2 as the height of our gradient (both are equal to the red line) then wg1 and wg2 as the width of our gradient (wg1 + wg2 = a). I will not going to detail the calculation but at then end we will have:
wg2 = (a²+c²-b²)/(2a)
wg1 = a - wg2
hg1 = hg2 = sqrt(b² - wg1²) = sqrt(c² - wg2²)
Now we have reached the limit of CSS as even with calc() we won't be able to implement this so we simply need to gather the final result manually and use them as fixed size:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2));
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
Bonus
We should not forget that we can also apply rotation and/or skew and we have more option to obtain more triangle:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2) - 0.5px);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49%,red 50%),
linear-gradient(to bottom left, transparent 49%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="transform:skewY(25deg)"></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;transform:rotate(20deg)" ></div>
And of course we should keep in mind the SVG solution which can be more suitable in some situation:
svg {
width:100px;
height:100px;
}
polygon {
fill:red;
}
<svg viewBox="0 0 100 100"><polygon points="0,100 0,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,23 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="20,60 50,43 80,100" /></svg>
SASS (SCSS) triangle mixin
I wrote this to make it easier (and DRY) to automatically generate a CSS triangle:
// Triangle helper mixin (by Yair Even-Or)
// #param {Direction} $direction - either `top`, `right`, `bottom` or `left`
// #param {Color} $color [currentcolor] - Triangle color
// #param {Length} $size [1em] - Triangle size
#mixin triangle($direction, $color: currentcolor, $size: 1em) {
$size: $size/2;
$transparent: rgba($color, 0);
$opposite: (top:bottom, right:left, left:right, bottom:top);
content: '';
display: inline-block;
width: 0;
height: 0;
border: $size solid $transparent;
border-#{map-get($opposite, $direction)}-color: $color;
margin-#{$direction}: -$size;
}
use-case example:
span {
#include triangle(bottom, red, 10px);
}
Playground page
Important note: if the triangle seems pixelated in some browsers, try one of the methods described here.
If you want to play around with border-size, width and height and see how those can create different shapes, try this:
const sizes = [32, 32, 32, 32];
const triangle = document.getElementById('triangle');
function update({ target }) {
let index = null;
if (target) {
index = parseInt(target.id);
if (!isNaN(index)) {
sizes[index] = target.value;
}
}
window.requestAnimationFrame(() => {
triangle.style.borderWidth = sizes.map(size => `${ size }px`).join(' ');
if (isNaN(index)) {
triangle.style[target.id] = `${ target.value }px`;
}
});
}
document.querySelectorAll('input').forEach(input => {
input.oninput = update;
});
update({});
body {
margin: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
#triangle {
border-style: solid;
border-color: yellow magenta blue black;
background: cyan;
height: 0px;
width: 0px;
}
#controls {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
display: flex;
box-shadow: 0 0 32px rgba(0, 0, 0, .125);
}
#controls > div {
position: relative;
width: 25%;
padding: 8px;
box-sizing: border-box;
display: flex;
}
input {
margin: 0;
width: 100%;
position: relative;
}
<div id="triangle" style="border-width: 32px 32px 32px 32px;"></div>
<div id="controls">
<div><input type="range" min="0" max="128" value="32" id="0" /></div>
<div><input type="range" min="0" max="128" value="32" id="1" /></div>
<div><input type="range" min="0" max="128" value="32" id="2" /></div>
<div><input type="range" min="0" max="128" value="32" id="3" /></div>
<div><input type="range" min="0" max="128" value="0" id="width" /></div>
<div><input type="range" min="0" max="128" value="0" id="height" /></div>
</div>
here is another fiddle:
.container:after {
position: absolute;
right: 0;
content: "";
margin-right:-50px;
margin-bottom: -8px;
border-width: 25px;
border-style: solid;
border-color: transparent transparent transparent #000;
width: 0;
height: 0;
z-index: 10;
-webkit-transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
bottom: 21px;
}
.container {
float: left;
margin-top: 100px;
position: relative;
width: 150px;
height: 80px;
background-color: #000;
}
.containerRed {
float: left;
margin-top: 100px;
position: relative;
width: 100px;
height: 80px;
background-color: red;
}
https://jsfiddle.net/qdhvdb17/
Others have already explained this well. Let me give you an animation which will explain this quickly: http://codepen.io/chriscoyier/pen/lotjh
Here is some code for you to play with and learn the concepts.
HTML:
<html>
<body>
<div id="border-demo">
</div>
</body>
</html>
CSS:
/*border-width is border thickness*/
#border-demo {
background: gray;
border-color: yellow blue red green;/*top right bottom left*/
border-style: solid;
border-width: 25px 25px 25px 25px;/*top right bottom left*/
height: 50px;
width: 50px;
}
Play with this and see what happens. Set height and width to zero. Then remove top border and make left and right transparent, or just look at the code below to make a css triangle:
#border-demo {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid blue;
}
I know this is an old one, but I'd like to add to this discussion that There are at least 5 different methods for creating a triangle using HTML & CSS alone.
Using borders
Using linear-gradient
Using conic-gradient
Using
transform and overflow
Using clip-path
I think that all have been covered here except for method 3, using the conic-gradient, so I will share it here:
.triangle{
width: 40px;
height: 40px;
background: conic-gradient(at 50% 50%,transparent 135deg,green 0,green 225deg, transparent 0);
}
<div class="triangle"></div>
use clip-path: polygon(50% 0%, 100% 100%, 0% 100%); for creating easy to Triangle
<div class="triangle"></div>
.triangle{width:200px; height:200px;background:#000;clip-path: polygon(50% 0%, 100% 100%, 0% 100%);}
After reading through the other answers here I see there are great explanations as to why the CSS triangle works the way it does. I would consider it to be somewhat of a trick, versus something that you could apply generically.
For something that's easier to read and maintain, I would recommend you define your geometry in SVG.
Then you can convert that SVG using data uri by adding the data:image/svg+xml, prefix. As a data uri, it can now be used as a background-image in a CSS. Because the SVG is in clear text, you can readily make updates to the geometry, stroke, and fill color.
div.tri {
width: 100px;
height: 100px;
display: inline-block;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="red" d="M31.345 29H1.655L16.5 1.96z"/></svg>');
}
<div>
<div class="tri"></div>
<div class="tri"></div>
<div class="tri"></div>
</div>
Try This:-
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
clip-path has the best result for me - works great for divs/containers with and without fixed dimensions:
.triangleContainer{
position: relative;
width: 500px;
height: 500px;
}
.triangleContainer::before{
content: "";
position: absolute;
background:blue;
top: 0;
left: 0;
width: 100%;
height: 100%;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
}

CSS Shapes and border [duplicate]

There're plenty of different CSS shapes over at CSS Tricks - Shapes of CSS and I'm particularly puzzled with a triangle:
#triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div id="triangle-up"></div>
How and why does it work?
CSS Triangles: A Tragedy in Five Acts
As alex said, borders of equal width butt up against each other at 45 degree angles:
When you have no top border, it looks like this:
Then you give it a width of 0...
...and a height of 0...
...and finally, you make the two side borders transparent:
That results in a triangle.
The borders use an angled edge where they intersect (45° angle with equal width borders, but changing the border widths can skew the angle).
div {
width: 60px;
border-width: 30px;
border-color: red blue green yellow;
border-style: solid;
}
<div></div>
Have a look to the jsFiddle.
By hiding certain borders, you can get the triangle effect (as you can see above by making the different portions different colours). transparent is often used as an edge colour to achieve the triangle shape.
Start with a basic square and borders. Each border will be given a different color so we can tell them apart:
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 200px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
which gives you this:
But there's no need for the top border, so set its width to 0px. Now our border-bottom of 200px will make our triangle 200px tall.
.triangle {
border-color: yellow blue red green;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
and we will get this:
Then to hide the two side triangles, set the border-color to transparent. Since the top-border has been effectively deleted, we can set the border-top-color to transparent as well.
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
finally we get this:
Different approach:
CSS3 triangles with transform rotate
Triangular shape is pretty easy to make using this technique. For people who prefer to see an animation explaining how this technique works here it is :
Link to the ANIMATION : How to make a CSS3 triangle.
And DEMO : CSS3 triangles made with transform rotate.
Otherwise, here is detailed explanation in 4 acts (this is not a tragedy) of how to make an isosceles right-angled triangle with one element.
Note 1 : for non isosceles triangles and fancy stuff, you can see step 4.
Note 2 : in the following snippets, the vendor prefixes aren't included. they are included in the codepen demos.
Note 3 : the HTML for the following explanation is always : <div class="tr"></div>
STEP 1 : Make a div
Easy, just make sure that width = 1.41 x height. You may use any techinque (see here) including the use of percentages and padding-bottom to maintain the aspect ratio and make a responsive triangle. In the following image, the div has a golden yellow border.
In that div, insert a pseudo element and give it 100% width and height of parent. The pseudo element has a blue background in the following image.
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr: before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
}
STEP 2 : Let's rotate
First, most important : define a transform origin. The default origin is in the center of the pseudo element and we need it at the bottom left. By adding this CSS to the pseudo element :
transform-origin:0 100%; or transform-origin: left bottom;
Now we can rotate the pseudo element 45 degrees clockwise with transform : rotate(45deg);
At this point, we have this CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 3 : hide it
To hide the unwanted parts of the pseudo element (everything that overflows the div with the yellow border) you just need to set overflow:hidden; on the container. after removing the yellow border, you get... a TRIANGLE! :
DEMO
CSS :
.tr {
width: 30%;
padding-bottom: 21.27%; /* = width / 1.41 */
position: relative;
overflow: hidden;
}
.tr:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #0079C6;
transform-origin: 0 100%;
transform: rotate(45deg);
}
STEP 4 : go further...
As shown in the demo, you can customize the triangles :
Make them thinner or flatter by playing with skewX().
Make them point left, right or any other direction by playing with the transform origin and rotation direction.
Make some reflexion with 3D transform property.
Give the triangle borders
Put an image inside the triangle
Much more... Unleash the powers of CSS3!
Why use this technique?
Triangle can easily be responsive.
You can make a triangle with border.
You can maintain the boundaries of the triangle. This means that you can trigger the hover state or click event only when the cursor is inside the triangle. This can become very handy in some situations like this one where each triangle can't overlay its neighbours so each triangle has its own hover state.
You can make some fancy effects like reflections.
It will help you understand 2d and 3d transform properties.
Why not use this technique?
The main drawback is the browser compatibility, the 2d transform properties are supported by IE9+ and therefore you can't use this technique if you plan on supporting IE8. See CanIuse for more info. For some fancy effects using 3d transforms like the reflection browser support is IE10+ (see canIuse for more info).
You don't need anything responsive and a plain triangle is fine for you then you should go for the border technique explained here : better browser compatibility and easier to understand thanks to the amazing posts here.
Here is an animation in JSFiddle I created for demonstration.
Also see snippet below.
This is an Animated GIF made from a Screencast
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0', 'margin-top': '120'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 20px 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Random version
/**
* Randomize array element order in-place.
* Using Durstenfeld shuffle algorithm.
*/
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
transforms = [
{'border-left-width' :'30', 'margin-left': '70'},
{'border-bottom-width' :'80'},
{'border-right-width' :'30'},
{'border-top-width' :'0', 'margin-top': '70'},
{'width' :'0'},
{'height' :'0'},
{'borderLeftColor' :'transparent'},
{'borderRightColor' :'transparent'}
];
transforms = shuffleArray(transforms)
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
for ( var i=0; i < transforms.length; i++ ) {
$(this)
.animate(transforms[i], duration)
}
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
All at once version
$('#a').click(function() {$('.border').trigger("click");});
(function($) {
var duration = 1000
$('.border').click(function() {
$(this)
.animate({'border-top-width': 0 ,
'border-left-width': 30 ,
'border-right-width': 30 ,
'border-bottom-width': 80 ,
'width': 0 ,
'height': 0 ,
'margin-left': 100,
'margin-top': 150,
'borderTopColor': 'transparent',
'borderRightColor': 'transparent',
'borderLeftColor': 'transparent'}, duration)
}).end()
}(jQuery))
.border {
margin: 50px;
width: 50px;
height: 50px;
border-width: 50px;
border-style: solid;
border-top-color: green;
border-right-color: yellow;
border-bottom-color: red;
border-left-color: blue;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>
Click it!<br>
<div class="border"></div>
Lets say we have the following div:
<div id="triangle" />
Now Edit the CSS step-by-step, so you will get clear idea what is happening around
STEP 1:
JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid black ;
border-right: 50px solid black;
border-bottom: 50px solid black;
border-top: 50px solid black;
}
This is a simple div. With a very simple CSS. So a layman can understand. Div has dimensions 150 x 150 pixels with the border 50 pixels. The image is attached:
STEP 2: JSfiddle Link:
#triangle {
background: purple;
width :150px;
height:150PX;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the border-color of all 4 sides. The image is attached.
STEP:3 JSfiddle Link:
#triangle {
background: purple;
width :0;
height:0;
border-left: 50px solid yellow ;
border-right: 50px solid green;
border-bottom: 50px solid red;
border-top: 50px solid blue;
}
Now I just changed the height & width of div from 150 pixels to zero. The image is attached
STEP 4: JSfiddle:
#triangle {
background: purple;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I have made all the borders transparent apart from the bottom border. The image is attached below.
STEP 5: JSfiddle Link:
#triangle {
background: white;
width :0px;
height:0px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid red;
border-top: 50px solid transparent;
}
Now I just changed the background color to white. The image is attached.
Hence we got the triangle we needed.
And now something completely different...
Instead of using css tricks don't forget about solutions as simple as html entities:
▲
Result:
▲
See: What are the HTML entities for up and down triangles?
Consider the below triangle
.triangle {
border-bottom:15px solid #000;
border-left:10px solid transparent;
border-right:10px solid transparent;
width:0;
height:0;
}
This is what we are given:
Why it came out in this shape? The below diagram explains the dimensions, note that 15px was used for the bottom border and 10px was used for left and right.
It's pretty easy to make a right-angle triangle also by removing the right border.
Taking it one step further, using css based on this I added arrows to my back and next buttons (yes I know its not 100% cross-browser, but slick none the less).
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
margin:20px auto;
}
.triangle-down {
border-bottom:none;
border-top: 100px solid red;
}
.triangle-left {
border-left:none;
border-right: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-right {
border-right:none;
border-left: 100px solid red;
border-bottom: 50px solid transparent;
border-top: 50px solid transparent;
}
.triangle-after:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid red;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-after-right:after {
border-right:none;
border-left: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
.triangle-before:before {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid blue;
margin:0 5px;
content:"";
display:inline-block;
}
.triangle-before-left:before {
border-left:none;
border-right: 5px solid blue;
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
}
<div class="triangle"></div>
<div class="triangle triangle-down"></div>
<div class="triangle triangle-left"></div>
<div class="triangle triangle-right"></div>
<a class="triangle-before triangle-before-left" href="#">Back</a>
<a class="triangle-after triangle-after-right" href="#">Next</a>
CSS clip-path
This is something I feel this question has missed; clip-path
clip-path in a nutshell
Clipping, with the clip-path property, is akin to cutting a shape (like a circle or a pentagon) from a rectangular piece of paper. The property belongs to the “CSS Masking Module Level 1” specification. The spec states, “CSS masking provides two means for partially or fully hiding portions of visual elements: masking and clipping”.
Extract from Smashing Magazine
clip-path will use the element itself rather than its borders to cut the shape you specify in its parameters. It uses a super simple percentage based co-ordinate system which makes editing it very easy and means you can pick it up and create weird and wonderful shapes in a matter of minutes.
Triangle Shape Example
div {
-webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
background: red;
width: 100px;
height: 100px;
}
<div></div>
Downside
It does have a major downside at the moment, one being it's major lack of support, only really being covered within -webkit- browsers and having no support on IE and only very partial in FireFox.
Resources
Here are some useful resources and material to help better understand clip-path and also start creating your own.
Clippy - A clip-path generator
The W3C Candidate Recommendation File
MDN clip-path documentation
clip-path Browser Support
Different approach. With linear gradient (for IE, only IE 10+).
You can use any angle:
.triangle {
margin: 50px auto;
width: 100px;
height: 100px;
/* linear gradient */
background: -moz-linear-gradient(-45deg, rgba(255,0,0,0) 0%, rgba(255,0,0,0) 50%, rgba(255,0,0,1) 50%, rgba(255,0,0,1) 100%);
/* FF3.6+ */
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,0)), color-stop(50%,rgba(255,0,0,1)), color-stop(100%,rgba(255,0,0,1)));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* Opera 11.10+ */
background: -ms-linear-gradient(-45deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* IE10+ */
background: linear-gradient(135deg, rgba(255,0,0,0) 0%,rgba(255,0,0,0) 50%,rgba(255,0,0,1) 50%,rgba(255,0,0,1) 100%);
/* W3C */;
}
<div class="triangle"></div>
Here is jsfiddle
OK, this triangle will get created because of the way that borders of the elements work together in HTML and CSS...
As we usually use 1 or 2px borders, we never notice that borders make a 45° angles to each others with the same width and if the width changes, the angle degree get changed as well, run the CSS code I created below:
.triangle {
width: 100px;
height: 100px;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
Then in the next step, we don't have any width or height, something like this:
.triangle {
width: 0;
height: 0;
border-left: 50px solid black;
border-right: 50px solid black;
border-bottom: 100px solid red;
}
<div class="triangle">
</div>
And now we make the left and right borders invisible to make our desirable triangle as below:
.triangle {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid red;
}
<div class="triangle"></div>
If you not willing to run the snippet to see the steps, I've created an image sequence to have a look at all steps in one image:
This is an old question, but I think will worth it to share how to create an arrow using this triangle technique.
Step 1:
Lets create 2 triangles, for the second one we will use the :after pseudo class and position it just below the other:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #ccc;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Step 2
Now we just have to set the predominant border color of the second triangle to the same color of the background:
.arrow{
width: 0;
height: 0;
border-radius: 50px;
display: inline-block;
position: relative;
}
.arrow:after{
content: "";
width: 0;
height: 0;
position: absolute;
}
.arrow-up{
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #333;
}
.arrow-up:after{
top: 5px;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 50px solid #fff;
right: -50px;
}
<div class="arrow arrow-up"> </div>
Fiddle with all the arrows:
http://jsfiddle.net/tomsarduy/r0zksgeu/
If you want to apply border to the triangle read this: Create a triangle with CSS?
Almost all the answers focus on the triangle built using border so I am going to elaborate the linear-gradient method (as started in the answer of #lima_fil).
Using a degree value like 45° will force us to respect a specific ratio of height/width in order to obtain the triangle we want and this won't be responsive:
.tri {
width:100px;
height:100px;
background:linear-gradient(45deg, transparent 49.5%,red 50%);
/*To illustrate*/
border:1px solid;
}
Good one
<div class="tri"></div>
bad one
<div class="tri" style="width:150px"></div>
bad one
<div class="tri" style="height:30px"></div>
Instead of doing this we should consider predefined values of direction like to bottom, to top, etc. In this case we can obtain any kind of triangle shape while keeping it responsive.
1) Rectangle triangle
To obtain such triangle we need one linear-gradient and a diagonal direction like to bottom right, to top left, to bottom left, etc
.tri-1,.tri-2 {
display:inline-block;
width:100px;
height:100px;
background:linear-gradient(to bottom left, transparent 49.5%,red 50%);
border:1px solid;
animation:change 2s linear infinite alternate;
}
.tri-2 {
background:linear-gradient(to top right, transparent 49.5%,red 50%);
border:none;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri-1"></div>
<div class="tri-2"></div>
2) isosceles triangle
For this one we will need 2 linear-gradient like above and each one will take half the width (or the height). It's like we create a mirror image of the first triangle.
.tri {
display:inline-block;
width:100px;
height:100px;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:50.3% 100%; /* I use a value slightly bigger than 50% to avoid having a small gap between both gradient*/
background-position:left,right;
background-repeat:no-repeat;
animation:change 2s linear infinite alternate;
}
#keyframes change {
from {
width:100px;
height:100px;
}
to {
height:50px;
width:180px;
}
}
<div class="tri"></div>
3) equilateral triangle
This one is a bit tricky to handle as we need to keep a relation between the height and width of the gradient. We will have the same triangle as above but we will make the calculation more complex in order to transform the isosceles triangle to an equilateral one.
To make it easy, we will consider that the width of our div is known and the height is big enough to be able to draw our triangle inside (height >= width).
We have our two gradient g1 and g2, the blue line is the width of the div w and each gradient will have 50% of it (w/2) and each side of the triangle sould be equal to w. The green line is the height of both gradient hg and we can easily obtain the formula below:
(w/2)² + hg² = w² ---> hg = (sqrt(3)/2) * w ---> hg = 0.866 * w
We can rely on calc() in order to do our calculation and to obtain the needed result:
.tri {
--w:100px;
width:var(--w);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:calc(var(--w)/2 + 0.5px) calc(0.866 * var(--w));
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
Another way is to control the height of div and keep the syntax of gradient easy:
.tri {
--w:100px;
width:var(--w);
height:calc(0.866 * var(--w));
display:inline-block;
background:
linear-gradient(to bottom right, transparent 49.8%,red 50%) left,
linear-gradient(to bottom left, transparent 49.8%,red 50%) right;
background-size:50.2% 100%;
background-repeat:no-repeat;
}
<div class="tri"></div>
<div class="tri" style="--w:80px"></div>
<div class="tri" style="--w:50px"></div>
4) Random triangle
To obtain a random triangle, it's easy as we simply need to remove the condition of 50% of each one BUT we should keep two condition (both should have the same height and the sum of both width should be 100%).
.tri-1 {
width:100px;
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 50%,red 0),
linear-gradient(to bottom left, transparent 50%,red 0);
background-size:20% 60%,80% 60%;
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri-1"></div>
But what if we want to define a value for each side? We simply need to do calculation again!
Let's define hg1 and hg2 as the height of our gradient (both are equal to the red line) then wg1 and wg2 as the width of our gradient (wg1 + wg2 = a). I will not going to detail the calculation but at then end we will have:
wg2 = (a²+c²-b²)/(2a)
wg1 = a - wg2
hg1 = hg2 = sqrt(b² - wg1²) = sqrt(c² - wg2²)
Now we have reached the limit of CSS as even with calc() we won't be able to implement this so we simply need to gather the final result manually and use them as fixed size:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2));
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49.5%,red 50%),
linear-gradient(to bottom left, transparent 49.5%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
Bonus
We should not forget that we can also apply rotation and/or skew and we have more option to obtain more triangle:
.tri {
--wg1: 20px;
--wg2: 60px;
--hg:30px;
width:calc(var(--wg1) + var(--wg2) - 0.5px);
height:100px;
display:inline-block;
background-image:
linear-gradient(to bottom right, transparent 49%,red 50%),
linear-gradient(to bottom left, transparent 49%,red 50%);
background-size:var(--wg1) var(--hg),var(--wg2) var(--hg);
background-position:
left bottom,right bottom;
background-repeat:no-repeat;
}
<div class="tri" ></div>
<div class="tri" style="transform:skewY(25deg)"></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;" ></div>
<div class="tri" style="--wg1:80px;--wg2:60px;--hg:100px;transform:rotate(20deg)" ></div>
And of course we should keep in mind the SVG solution which can be more suitable in some situation:
svg {
width:100px;
height:100px;
}
polygon {
fill:red;
}
<svg viewBox="0 0 100 100"><polygon points="0,100 0,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,0 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="0,100 50,23 100,100" /></svg>
<svg viewBox="0 0 100 100"><polygon points="20,60 50,43 80,100" /></svg>
SASS (SCSS) triangle mixin
I wrote this to make it easier (and DRY) to automatically generate a CSS triangle:
// Triangle helper mixin (by Yair Even-Or)
// #param {Direction} $direction - either `top`, `right`, `bottom` or `left`
// #param {Color} $color [currentcolor] - Triangle color
// #param {Length} $size [1em] - Triangle size
#mixin triangle($direction, $color: currentcolor, $size: 1em) {
$size: $size/2;
$transparent: rgba($color, 0);
$opposite: (top:bottom, right:left, left:right, bottom:top);
content: '';
display: inline-block;
width: 0;
height: 0;
border: $size solid $transparent;
border-#{map-get($opposite, $direction)}-color: $color;
margin-#{$direction}: -$size;
}
use-case example:
span {
#include triangle(bottom, red, 10px);
}
Playground page
Important note: if the triangle seems pixelated in some browsers, try one of the methods described here.
If you want to play around with border-size, width and height and see how those can create different shapes, try this:
const sizes = [32, 32, 32, 32];
const triangle = document.getElementById('triangle');
function update({ target }) {
let index = null;
if (target) {
index = parseInt(target.id);
if (!isNaN(index)) {
sizes[index] = target.value;
}
}
window.requestAnimationFrame(() => {
triangle.style.borderWidth = sizes.map(size => `${ size }px`).join(' ');
if (isNaN(index)) {
triangle.style[target.id] = `${ target.value }px`;
}
});
}
document.querySelectorAll('input').forEach(input => {
input.oninput = update;
});
update({});
body {
margin: 0;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
#triangle {
border-style: solid;
border-color: yellow magenta blue black;
background: cyan;
height: 0px;
width: 0px;
}
#controls {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
display: flex;
box-shadow: 0 0 32px rgba(0, 0, 0, .125);
}
#controls > div {
position: relative;
width: 25%;
padding: 8px;
box-sizing: border-box;
display: flex;
}
input {
margin: 0;
width: 100%;
position: relative;
}
<div id="triangle" style="border-width: 32px 32px 32px 32px;"></div>
<div id="controls">
<div><input type="range" min="0" max="128" value="32" id="0" /></div>
<div><input type="range" min="0" max="128" value="32" id="1" /></div>
<div><input type="range" min="0" max="128" value="32" id="2" /></div>
<div><input type="range" min="0" max="128" value="32" id="3" /></div>
<div><input type="range" min="0" max="128" value="0" id="width" /></div>
<div><input type="range" min="0" max="128" value="0" id="height" /></div>
</div>
here is another fiddle:
.container:after {
position: absolute;
right: 0;
content: "";
margin-right:-50px;
margin-bottom: -8px;
border-width: 25px;
border-style: solid;
border-color: transparent transparent transparent #000;
width: 0;
height: 0;
z-index: 10;
-webkit-transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
transition: visibility 50ms ease-in-out,opacity 50ms ease-in-out;
bottom: 21px;
}
.container {
float: left;
margin-top: 100px;
position: relative;
width: 150px;
height: 80px;
background-color: #000;
}
.containerRed {
float: left;
margin-top: 100px;
position: relative;
width: 100px;
height: 80px;
background-color: red;
}
https://jsfiddle.net/qdhvdb17/
Others have already explained this well. Let me give you an animation which will explain this quickly: http://codepen.io/chriscoyier/pen/lotjh
Here is some code for you to play with and learn the concepts.
HTML:
<html>
<body>
<div id="border-demo">
</div>
</body>
</html>
CSS:
/*border-width is border thickness*/
#border-demo {
background: gray;
border-color: yellow blue red green;/*top right bottom left*/
border-style: solid;
border-width: 25px 25px 25px 25px;/*top right bottom left*/
height: 50px;
width: 50px;
}
Play with this and see what happens. Set height and width to zero. Then remove top border and make left and right transparent, or just look at the code below to make a css triangle:
#border-demo {
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid blue;
}
I know this is an old one, but I'd like to add to this discussion that There are at least 5 different methods for creating a triangle using HTML & CSS alone.
Using borders
Using linear-gradient
Using conic-gradient
Using
transform and overflow
Using clip-path
I think that all have been covered here except for method 3, using the conic-gradient, so I will share it here:
.triangle{
width: 40px;
height: 40px;
background: conic-gradient(at 50% 50%,transparent 135deg,green 0,green 225deg, transparent 0);
}
<div class="triangle"></div>
use clip-path: polygon(50% 0%, 100% 100%, 0% 100%); for creating easy to Triangle
<div class="triangle"></div>
.triangle{width:200px; height:200px;background:#000;clip-path: polygon(50% 0%, 100% 100%, 0% 100%);}
After reading through the other answers here I see there are great explanations as to why the CSS triangle works the way it does. I would consider it to be somewhat of a trick, versus something that you could apply generically.
For something that's easier to read and maintain, I would recommend you define your geometry in SVG.
Then you can convert that SVG using data uri by adding the data:image/svg+xml, prefix. As a data uri, it can now be used as a background-image in a CSS. Because the SVG is in clear text, you can readily make updates to the geometry, stroke, and fill color.
div.tri {
width: 100px;
height: 100px;
display: inline-block;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="red" d="M31.345 29H1.655L16.5 1.96z"/></svg>');
}
<div>
<div class="tri"></div>
<div class="tri"></div>
<div class="tri"></div>
</div>
Try This:-
.triangle {
border-color: transparent transparent red transparent;
border-style: solid;
border-width: 0px 200px 200px 200px;
height: 0px;
width: 0px;
}
<div class="triangle"></div>
clip-path has the best result for me - works great for divs/containers with and without fixed dimensions:
.triangleContainer{
position: relative;
width: 500px;
height: 500px;
}
.triangleContainer::before{
content: "";
position: absolute;
background:blue;
top: 0;
left: 0;
width: 100%;
height: 100%;
clip-path: polygon(50% 0, 0 100%, 100% 100%);
}

Resources