CSS Transform to skew the shape to a trapezium - css

I want to be able to skew an element in the way the image displays below.
I have been playing around with it, but dont seem to be able to get close to replicating that shape.
My css code is
transform:skew(30deg,30deg);
Is transform even the right way to do this? Please let me know the best, most browser compatible, solution.

You can apply some rotate transform around the X axis and apply an appropriate pespective before:
div {
width:300px;
height:200px;
background:url(http://placekitten.com/300/200);
border:2px solid red;
border-top-width:4px;
border-bottom-width:1px;
-webkit-transform: perspective(200px) rotateX(40deg);
margin:100px;
}
Demo

Try this:
Html
<div class="trapezium"></div>
StyleSheet
.trapezium {
border-bottom: 80px solid #fff;
border-left: 45px solid transparent;
border-right: 45px solid transparent;
padding: 0 8px 0 0;
height: 0;
width: 120px;
position: relative;
margin: 2em auto;
}
.trapezium:before {
border-bottom: 90px solid #000;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
padding: 0 8px 0 0;
height: 0;
width: 130px;
position: absolute;
bottom: -85px;
left: -55px;
content: "";
z-index: -1;
}
Here is the Demo

Related

CSS - Creating a custom arrow

Hi I am trying to create a custom arrow in CSS that looks like the image below.
Ideally I want to create this by overlaying two shapes a triangle and a rectangle (maybe using CSS :after and :before) but I'm not too savvy when it comes to CSS so I have been struggling.I started by just using borders but doesn't look like it is going to work
So far I just have:
.arrow {
width: 0;
height: 0;
border-top: 60px solid transparent;
border-bottom: 60px solid transparent;
border-left: 60px solid #ccc;
}
<div class="arrow"></div>
Not too hard to make using the :before pseudo element and some transforms:
.container {
padding: 100px;
}
.arrow {
display: inline-block;
height: 150px;
background: #000;
width: 75px;
}
.arrow:before {
content: "";
border-top: 100px solid #000;
border-left: 100px solid transparent;
border-right: 100px solid transparent;
border-bottom: 100px solid transparent;
transform: rotateZ(180deg) translateY(100%) translateX(31%);
position: relative;
display: inline-block;
}
<div class="container">
<div class="arrow"></div>
</div>
Here's another option.
.arrow{
width: 0;
height: 0;
border-top: 60px solid transparent;
border-bottom: 60px solid transparent;
border-left: 60px solid #ccc;
position: relative;
margin: 0 0 0 100px;
}
.arrow::before{
content: "";
height:50px;
width:80px;
background: #ccc;
position: absolute;
top: 0;
margin: -100%;
display: block;
transform: translateX(-160%) translateY(-50%);
}
<div class="arrow"></div>
Create one rectangle and then add triangle on top with :before pseudo-element and that is it.
.arrow {
width: 36px;
height: 50px;
background: #3F3F3F;
position: relative;
margin: 60px;
}
.arrow:before {
content: '';
border-style: solid;
border-width: 0 40px 40px 40px;
border-color: transparent transparent #3F3F3F transparent;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -100%);
}
<div class="arrow"></div>
To explain and demonstrate:
A CSS arrow is created by coloring 1 border side, and then moving the other 3 sides in towards the middle of the shape as transparent so they don't show but cut the remaining colored side into a triangle. The shorthand for this is TOP RIGHT BOTTOM LEFT. So to make a triangle pointing upwards you use the third property or bottom.
Using pseudo elements (incase you want the arrow added to another element) you need content:'' to "create" the pseudo element. I've set them as display: block so that they are in the flow and interact with eachother (rather than being laid on top of one another).
By giving the rectangle position: relative you can then use left: 30px (half of the triangle width) to position it in the middle of the triangle.
.arrowWrapper:before {
content: '';
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 0 60px 60px 60px;
border-color: transparent transparent black transparent;
/* border-color: TOP RIGHT BOTTOM LEFT; */
}
.arrowWrapper:after {
content: '';
position: relative;
display: block;
width: 60px;
height: 60px;
background: black;
left: 30px;
}
<div class="arrowWrapper"></div>
Lifted and modified from http://www.cssportal.com/css3-shapes/:
#eq-triangle {
width: 0;
height: 0;
border-bottom: 104px solid blue;
border-left: 60px solid transparent;
border-right: 60px solid transparent;
}
#rectangle {
width: 40px;
height: 80px;
background: blue;
margin-left: 40px;
}
<div id="eq-triangle"></div>
<div id="rectangle"></div>

Possible to create real arrow via CSS and rotate it?

Is it possible to create a complete arrow using CSS?
This is how I create just the head of the arrow: http://jsfiddle.net/2fsoz6ye/
#demo:after {
content: ' ';
height: 0;
position: absolute;
width: 0;
border: 10px solid transparent;
border-top-color: #333;
}
But I also need the back part of the arrow. Just to look like this:
And after this I want to rotate the CSS-arrow, so I would be able to use it dynamically... i.e. pointing to the top, left, 45°...
Just have a look at this fiddle: http://jsfiddle.net/2fsoz6ye/2/
.container{
transform: rotate(30deg);
width:60px; height:40px; background:#ccc; margin:100px auto;}
.arrow-right {
width: 0;
height: 0;
border-top: 40px solid transparent;
border-bottom: 40px solid transparent;
border-left: 40px solid #ccc;
float:right;
margin-top:-20px;
margin-right:-40px;
}

making borders around CSS shapes

So I'm drawing elements in CSS, using this tutorial as a guide. I need some help with borders, though. For instance, here's my code for a curved trapezoid:
.foobar {
height: 0px;
width: 140px;
position: relative;
border-bottom: 200px solid red;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
border-bottom-left-radius: 150px 70px;
border-bottom-right-radius: 100px 25px;
}
The problem: I want to draw a 1px line border around the foobar element, but I'm already using the border properties to draw the element in the first place.
Is there an easy way to do this? My sense is that I'll have to create a shadow element that is the same shape as -- but slightly larger than -- the foobar element.
Thanks in advance!
You can position a :pseudo element behind with slightly adjusted dimensions.
.foobar, .foobar:before {
height: 0px;
width: 140px;
position: relative;
border-bottom: 200px solid red;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
border-bottom-left-radius: 150px 70px;
border-bottom-right-radius: 100px 25px;
}
.foobar:before {
content: "";
display:block;
position: absolute;
left: -31px;
top: -1px;
width: 142px;
z-index: -1;
border-bottom: 202px solid black;
/* add these lines if you're a pixel perfectionist */
border-bottom-left-radius: 150px 71px;
border-bottom-right-radius: 100px 26px;
}
http://jsfiddle.net/4vNGL/2
You can use a pseudo element drawn behind with same rules with a small increase of scale.
.foobar, .foobar:before {
height: 0px;
width: 140px;
position: relative;
border-bottom: 200px solid red;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
border-bottom-left-radius: 150px 70px;
border-bottom-right-radius: 100px 25px;
position:relative;
}
.foobar:before {
content:'';
position:absolute;
display:block;
z-index:-1;
top:0;
left:-30px;
width: 140px;
-webkit-transform-origin:center;
-webkit-transform:scale(1.03);/* adapt here the width of your fake border */
transform-origin:center;
transform:scale(1.03);
border-bottom: 200px solid black; /* color of fake border */
}
http://codepen.io/gc-nomade/pen/eDIGJ
You can even play with both pseudo-element and still add some shadows: http://codepen.io/gc-nomade/pen/axmsc

CSS Triangle For Testimonial Box

I have a testimonials box that I would like to add a triangle to.
.arrow {
float: left;
margin-left: 25px;
margin-top: 20px;
width: 0;
height: 0;
border-top: 20px solid #eee;
border-left: 0px solid transparent;
border-right: 25px solid transparent;
}
The problem is the triangle ends up being solid, as opposed to white with a gray border. Below is a screenshot of how the CSS currently displays. Thanks in advance for the time and help.
You can create two triangles, one that overlaps the other, to create this bordered effect. You can do this with the ::before and ::after pseudo-elements so that you don't even have any superfluous HTML.
http://jsfiddle.net/7K2c4/
.mybox {
position: relative;
border: 1px solid #ccc;
}
.mybox:before,
.mybox:after { position: absolute;
left: 20px;
bottom: -19px;
display: block;
width: 0;
height: 0;
border-width: 0 25px 20px;
border-style: solid;
border-color: transparent;
border-left-color: #fff;
content: ' ';
}
.mybox:before { left: 19px;
bottom: -21px;
border-left-color: #ccc; }
You can place another triangle over it, smaller with the same color of the box background. You don't even need to create another HTML element, just use a pseudo-element selector.

CSS triangle custom border color

Attempting to use a custom hex color for my css triangle (border). However since it uses border properties I am unsure how to go about doing this. I would like to steer clear of javascript and css3 simply because of compatibility. I am trying to have the triangle have a white background with a 1px border (around the angled sides of the triangle) with color #CAD5E0. Is this possible? Here's what I have so far:
.container {
margin-left: 15px;
width: 200px;
background: #FFFFFF;
border: 1px solid #CAD5E0;
padding: 4px;
position: relative;
min-height: 200px;
}
.container:after {
content: '';
display: block;
position: absolute;
top: 10px;
left: 100%;
width: 0;
height: 0;
border-color: transparent transparent transparent #CAD5E0;
border-style: solid;
border-width: 10px;
}​
My fiddle: http://jsfiddle.net/4ZeCz/
You actually have to fake it with two triangles....
.container {
margin: 15px 30px;
width: 200px;
background: #fff;
border: 1px solid #a00;
position: relative;
min-height: 200px;
padding: 20px;
text-align: center;
color: #fff;
font: bold 1.5em/180px Helvetica, sans-serif;
text-shadow: 0 0 1px #000;
}
.container:after,
.container:before {
content: '';
display: block;
position: absolute;
left: 100%;
width: 0;
height: 0;
border-style: solid;
}
.container:after {
top: 10px;
border-color: transparent transparent transparent #fdd;
border-width: 10px;
}
.container:before {
top: 9px;
border-color: transparent transparent transparent #a00;
border-width: 11px;
}
Updated Fiddle here
I know you accept that but check this one also with less css:
.container {
margin-left: 15px;
width: 200px;
background: #FFFFFF;
border: 1px solid #CAD5E0;
padding: 4px;
position: relative;
min-height: 200px;
}
.container:after {
content: '';
display: block;
position: absolute;
top: 10px;
right:-7px;
width: 10px;
height: 10px;
background: #FFFFFF;
border-right:1px solid #CAD5E0;
border-bottom:1px solid #CAD5E0;
-moz-transform:rotate(-45deg);
-webkit-transform:rotate(-45deg);
}
http://jsfiddle.net/4ZeCz/3/
I think this is a simpler one using clip-path:
.container {
width: 150px;
min-height: 150px;
background: #ccc;
padding: 8px;
padding-right: 6%;
display: inline-block;
clip-path: polygon(0% 0%,0% 100%,90% 100%,90% 5%,100% 10%,90% 15%,90% 0%);
}
<div class="container">
test content
</div>
Another way to accomplish this, especially for somebody who needs this to work with equilateral or even scalene triangles like I did, is to use filter: drop-shadow(...) with multiple values and no blur radius. This has the added benefit of not needing multiple elements, or access to both :before and :after (I was trying to accomplish this with :after content that was inline, so wanted to avoid absolute positioning too).
For the above case, the :after's CSS could look like this (fiddle):
.container {
margin-left: 15px;
width: 200px;
background: #FFFFFF;
border: 1px solid #CAD5E0;
padding: 4px;
position: relative;
min-height: 200px;
}
.container:after {
content: '';
display: block;
position: absolute;
top: 10px;
left: 100%;
width: 0;
height: 0;
border-style: solid;
border-width: 20px 0 40px 15px; /* skewed to show support for non-right-angle triangles */
border-color: transparent transparent transparent #fff;
filter: drop-shadow(1px 0 0 #CAD5E0) drop-shadow(0 .5px 0 #CAD5E0);
}
<div class="container">
Test Container
</div>
I think there are some limitations or weirdness, though:
No support in IE11 (though seems fine in FF, Chrome, and Edge)
I'm not quite sure why .5px for the <offset-y> value in the second drop-shadow() above appears more like 1px than 1px would have, though I imagine it's related to trigonometry (though at least on my monitor I see no difference between the actual trig-based values or .5px or even .1px for that matter).
Borders greater than 1px (well, their appearance that way) don't seem to work well. Or at least I haven't found the solution, though see below for a less-than-optimal way to go a little bigger. (I would think the documented-but-unsupported 4th parameter (<spread-radius>) of drop-shadow() might be what I'm really looking for instead of multiple filter values, but adding it in just broke things entirely.) Here you can see what starts to happen when going beyond 1px (fiddle):
.container {
background-color: #eee;
padding: 1em;
}
.container:after {
content: "";
width: 0;
height: 0;
border-style: solid;
border-width: 20.4px 10px 0 10px;
border-color: yellow transparent transparent transparent;
margin-left: .25em;
display: inline-block;
filter: drop-shadow(-6px -4px 0 green) drop-shadow(6px -4px 0 red) drop-shadow(0 6px 0 blue);
}
<div class="container">
Test Container
</div>
Notice the funniness that the first one (green) gets applied once, but the second one (red) is getting applied both to the yellow triangle created via border as well as the green drop-shadow(), and the last one (blue) gets applied to all of the above. (Perhaps that's also related to the .5px appearance thing).
But I guess you can take advantage of these drop-shadows building on each other if you need something wider-looking than 1px, by changing them to something like the following (fiddle):
filter: drop-shadow(0 0 2.5px red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red) drop-shadow(0 0 0 red);
where the very first one has a blur-radius set (2.5px in this case, though the result appears multiplied), and all the rest have blur at 0. But this will only work for the same color on all sides, and it results in some rounded-looking corners as well as quite rough edges the bigger you go.
.triangle{
position: absolute;
width:0px;
height:0px;
border-left: 45px solid transparent;
border-right: 45px solid transparent;
border-bottom: 72px solid #DB5248;
}
.triangle:after{
position: relative;
content:"!";
top:8px;
left:-8px;
color:#DB5248;
font-size:40px;
}
.triangle:before{
content:".";
color: #DB5248;
position: relative;
top:-14px;
left:-43px;
border-left: 41px solid transparent;
border-right: 41px solid transparent;
border-bottom: 67px solid white;
}

Resources