CSS Transform Skew [duplicate] - css

This question already has answers here:
Responsive CSS Trapezoid Shape
(2 answers)
Closed 3 years ago.
Does anyone know how to achieve skew like this:
Using CSS's new transform property?
As you can see I'm trying to skew both corners, anyone know if this is possible?

.red.box {
background-color: red;
transform: perspective( 600px ) rotateY( 45deg );
}
Then HTML:
<div class="box red"></div>
from http://desandro.github.com/3dtransforms/docs/perspective.html

CSS:
#box {
width: 200px;
height: 200px;
background: black;
position: relative;
-webkit-transition: all 300ms ease-in;
}
#box:hover {
-webkit-transform: rotate(-180deg) scale(0.8);
}
#box:after, #box:before {
display: block;
content: "\0020";
color: transparent;
width: 211px;
height: 45px;
background: white;
position: absolute;
left: 1px;
bottom: -20px;
-webkit-transform: rotate(-12deg);
-moz-transform: rotate(-12deg);
}
#box:before {
bottom: auto;
top: -20px;
-webkit-transform: rotate(12deg);
-moz-transform: rotate(12deg);
}​
HTML:
<div id=box></div>​
Works in Chrome and FF 4: http://jsfiddle.net/rudiedirkx/349x9/
This might help: http://jsfiddle.net/rudiedirkx/349x9/2880/
And this too (from Erwinus' comment): http://css-tricks.com/examples/ShapesOfCSS/

I think you mean webkit transform.. please check this URL out
http://www.the-art-of-web.com/css/3d-transforms/ it could help you.

You can use -webkit-perspective and -webkit-transform together.
<div style="-webkit-perspective:300;">
<div style="-webkit-transform:rotate3d(0, 1, 0, 30deg);width:200px;height:200px;background:#D73913;"></div>
</div>
This works only in Safari.

Use this css code. Set the numbers according to your need
-webkit-transform: translateX(16em) perspective(600px) rotateY(10deg);
-moz-transform: translateX(16em) perspective(600px) rotateY(10deg);
-ms-transform: translateX(16em) perspective(600px) rotateY(10deg);
-o-transform: translateX(16em) perspective(600px) rotateY(10deg);
transform: translateX(16em) perspective(600px) rotateY(10deg);

Just in case you want, use matrix 3d.
transform:matrix3d(
1,0,1,0.003,
0,1,0,0,
0,0,1,0,
0,0,0,1);
http://codepen.io/Logo/pen/jEMVpo

.size{
width: 200px;
height: 200px;
}
.boxContainer{
-webkit-perspective:100;
}
.box{
background: blue;
-webkit-transform-origin-x:0;
-webkit-transform: rotateY(10deg);
}
<div class="size boxContainer">
<div class="size box">
</div>
</div>
This worked for me.

2 more methods:
As seen on https://css-tricks.com/examples/ShapesOfCSS/#trapezoid you can use border:
#box {
border-left: 200px solid black;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
width: 0;
height: 100px;
}
but it can't have contents, because it's all border.
Example: http://jsfiddle.net/rudiedirkx/349x9/3112/
Use CSS' actual 'skew' transform:
#box {
width: 200px;
height: 170px;
margin-top: 30px;
background-color: black;
transform: skewY(10deg);
position: relative;
z-index: 1; /* doesn't work? */
}
#box:before {
content: "";
display: block;
width: 200px;
height: 80px;
position: absolute;
bottom: -40px;
left: 0;
background-color: black;
transform: skewY(-20deg);
z-index: -1; /* doesn't work? */
}
I can't seem to position the pseudo element behind the main element though, so the pseudo actually falls over the main element's content, if any.
Example: http://jsfiddle.net/rudiedirkx/349x9/3113/

Related

CSS 3D Transformation leaves Gaps

I am trying to make a simple cube in CSS using a before and after pseudo selector.
This however leaves a slight gap between the top of the cube and the sides where you can see the magenta background through the cube.
body{background:magenta;perspective: 300000;}
div{
width:100px;
height:100px;
background:yellow;
transform-style: preserve-3d;
transform: rotateX(60deg) rotateZ(-45deg) translateX(50px) translateY(100px);
}
/* Right */
div:after {
background: #c5c500;
transform: rotateX(-90deg);
transform-origin: 100% 0%;
top: 100%;
width: 100%;
height: 100px;
content: '';
position: absolute;
backface-visibility: hidden;
background-clip:content-box;
}
/* Left */
div:before {
background: #f3f370;
transform: translateZ(-100px) rotateY(-90deg);
transform-origin: 0 100%;
width: 100px;
height: 100%;
content: '';
position: absolute;
backface-visibility: hidden;
background-clip:content-box;
}
You can see this in action in this fiddle http://jsfiddle.net/04ggen30/
How can I get rid of this gap so that the background is not visible through the cube?
It aren't really gaps.
In the border, there are pixels where the element only covers a fraction of the pixel. The antialiasing blends the color of the element with the color of the background. Repeat this for the other face of the cube, covering also part of the pixel, and there is still a small contribution of the background to the result.
You can solve it if you set 3 divs in the HTML, one for each face.
Now, you can use pseudo elements, moved 1px inside the cube, to make it more opaque
body{background:magenta;perspective: 300000;}
div{
width:100px;
height:100px;
background:yellow;
transform-style: preserve-3d;
transform: rotateX(60deg) rotateZ(-45deg) translateX(50px) translateY(100px);
}
.right {
background: #c5c500;
transform: rotateX(-90deg);
transform-origin: 100% 0%;
top: 100%;
width: 100%;
height: 100px;
position: absolute;
backface-visibility: hidden;
background-clip:content-box;
}
.left {
background: #f3f370;
transform: translateZ(-100px) rotateY(-90deg);
transform-origin: 0 100%;
width: 100px;
height: 100%;
position: absolute;
backface-visibility: hidden;
background-clip:content-box;
}
.right::after, .left:after {
content: '';
top: 0px;
width: inherit;
height: inherit;
position: absolute;
background: inherit;
transform: translateZ(-1px);
}
<div>
<div class="right"></div>
<div class="left"></div>
</div>
Another posibility using shadows and a single element
body{background:magenta;perspective: 300000;}
div{
width:100px;
height:100px;
background:yellow;
transform-style: preserve-3d;
transform: rotateX(60deg) rotateZ(-45deg) translateX(50px) translateY(100px);
}
/* Right */
div:after {
background: #c5c500;
transform: rotateX(-90deg);
transform-origin: 100% 0%;
top: 100%;
width: 100%;
height: 100px;
content: '';
position: absolute;
backface-visibility: hidden;
background-clip:content-box;
box-shadow: 0px -1px 0px 0px #c5c500;
}
/* Left */
div:before {
background: #f3f370;
transform: translateZ(-100px) rotateY(-90deg);
transform-origin: 0 100%;
width: 100px;
height: 100%;
content: '';
position: absolute;
backface-visibility: hidden;
background-clip:content-box;
box-shadow: 1px 1px 0px 0px #f3f370;
}
<div></div>
I just changed the width: 101px; to both before and after elements. You can see this fiddle http://jsfiddle.net/04ggen30/2/. Or you can change the transform property with transform: translateZ(-99px) rotateY(-90deg); just decreased translateZ from -100px to 99px.

Image with right edge triangle

I am some time trying to make a complicated effect on the image, I made some attempts however not got it. I need this effect only in css without using javascript.
CSS
.container{
width: 500px;
background-color: #0c2f45;
}
.image-container {
background-color: #194c6e;
width: 266px;
}
.image-container img{
width: 250px;
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";
}
jsfiddle
You could achieve something like this through a couple of transformed pseudo elements*. By skewing the two pesudos, you can create the triangular effect.
A quick demo would be:
div {
height: 200px;
width: 300px;
background: url(http://lorempixel.com/300/200);
position: relative;
overflow: hidden;
}
div:before,
div:after {
content: "";
position: absolute;
height: 50%;
width: 20%;
background: tomato;
border-left: 10px solid firebrick;
left: 80%;
}
div:before {
top: 0;
transform: skewX(10deg);
}
div:after {
top: 50%;
transform: skewX(-10deg);
}
<div></div>
* this would assume you wish to have a solid colour on the right hand side

Left/right transparent cut out arrow

I am aware this has been answered previously however that was for the bottom of a div and I cannot work out how to do it for the left and right of a div.
I am trying to acheive the same effect as this:
BODY {
background: url(http://farm6.staticflickr.com/5506/9699081016_ba090f1238_h.jpg) 0 -100px;
}
#wrapper {
overflow: hidden;
height: 116px;
}
#test {
height: 100px;
background-color: #ccc;
position: relative;
}
#test:before {
content: "";
position: absolute;
left: -6px;
width: 50%;
height: 16px;
top: 100px;
background-color: #ccc;
-webkit-transform: skew(-40deg);
-moz-transform: skew(-40deg);
-o-transform: skew(-40deg);
-ms-transform: skew(-40deg);
transform: skew(-40deg);
}
#test:after {
content: "";
position: absolute;
right: -6px;
width: 50%;
height: 16px;
top: 100px;
background-color: #ccc;
-webkit-transform: skew(40deg);
-moz-transform: skew(40deg);
-o-transform: skew(40deg);
-ms-transform: skew(40deg);
transform: skew(40deg);
}
<div id="wrapper">
<div id="test"></div>
</div>
But with the cut out on the left and another with the cut out on the right.
This solution is adapted from this answer : Transparent arrow/triangle
The point is to use two skewed pseudo elements to make the transparent cut out arrow. Both pseudo elements are absolutely positioned and skewed.
In the following demo, the arrow is on the left. To make the same on on the right, you could duplicate the .arrow element and use scaleX(-1) + positioning on the second one. This will allow you to change both sides at the same time and have less CSS. Or you can make a new element based on the first one and change the positioning and skew properties.
DEMO
.wrap {
position: relative;
overflow: hidden;
width: 70%;
margin: 0 auto;
}
.wrap img {
width: 100%;
height: auto;
display: block;
}
.arrow {
position: absolute;
left: 0; top:0;
width: 3%;
height:100%;
background-color: rgba(255,255,255,.8);
}
.arrow:before, .arrow:after {
content:'';
position: absolute;
left: 100%;
width: 100%;
height:50%;
background-color: inherit;
}
.arrow:before {
bottom: 50%;
-ms-transform-origin: 0 100%;
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
-ms-transform: skewY(-45deg);
-webkit-transform: skewY(-45deg);
transform: skewY(-45deg);
}
.arrow:after {
top: 50%;
-ms-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-ms-transform: skewY(45deg);
-webkit-transform: skewY(45deg);
transform: skewY(45deg);
}
<div class="wrap">
<img src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" />
<div class="arrow"></div>
</div>
For the same output, you can use an svg :
DEMO
.wrap {
position: relative;
overflow: hidden;
width: 70%;
margin: 0 auto;
}
.wrap img {
width: 100%;
height: auto;
display: block;
}
.arrow{
position:absolute;
left:0; top:0;
height:100%;
}
<div class="wrap">
<img src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" />
<svg class="arrow" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 10 100">
<path d="M-1 -1 H10 V45 L5 50 L10 55 V101 H-1z" fill="#fff" fill-opacity="0.8" stroke-width="0"/>
</svg>
</div>
It can be made with a single element using inset box-shadow and pseudo-elements :before and :after
The elements are skewed by 45deg and -45deg to create the transparent gap. Inset box-shadow is used to increase the width of the arrow banner.
Fiddle (1 element)
body {
font-size: 10px;
}
div {
background: url('https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg');
height: 33.3em;
width: 50em;
position: relative;
overflow: hidden;
box-shadow: inset 2em 0 0 0 rgba(255, 255, 255, 0.6);
}
div:before, div:after {
content: "";
position: absolute;
left: 2em;
background-color: rgba(255, 255, 255, 0.6);
height: 25em;
width: 2em;
-webkit-transform-origin: 0% 0%;
-moz-transform-origin: 0% 0%;
-ms-transform-origin: 0% 0%;
transform-origin: 0% 0%;
}
div:before {
bottom: -8.35em;
-webkit-transform: skewY(45deg);
-moz-transform: skewY(45deg);
-ms-transform: skewY(45deg);
transform: skewY(45deg);
}
div:after {
top: -8.35em;
-webkit-transform: skewY(-45deg);
-moz-transform: skewY(-45deg);
-ms-transform: skewY(-45deg);
transform: skewY(-45deg);
}
<div></div>
Bugs : Browser rendering of box-shadow isn't consistent when using veiwport units. On zooming-out to 33%, GC shows 1px gap b/w pseudo-element and box-shadow. This bug doesn't occur with px and em units on zooming.
A better approach than the one given above would be to use one element on top of img element. The rest properties (overflow: hidden;, box-shadow) too are used, but this doesn't have the gap between the arrow even on zooming.
Fiddle (2 elements)
Note :
Ideas used from earlier post here.
All measurements are done in em with a set font-size of 10px.
You could use CSS3's clip-path property but it's a bit bleeding-edge. However, if you don't need to support IE there are plenty of useful examples at http://css-tricks.com/clipping-masking-css/
div {background: yellow; width:400px; height:300px;}
div img {
-webkit-clip-path: polygon(10% 0%, 90% 0%, 90% 100%, 90% 40%, 100% 50%, 90% 60%, 90% 100%, 10% 100%, 10% 60%, 0% 50%, 10% 40%);
clip-path: polygon(10% 0%, 90% 0%, 90% 100%, 90% 40%, 100% 50%, 90% 60%, 90% 100%, 10% 100%, 10% 60%, 0% 50%, 10% 40%);
}
<div><img src="http://lorempixel.com/400/300/nature/" /></div>
Hey I just modified your existing one. Probably could have done it a bit cleaner but you get the idea. This is the left side. Pretty easy to swap it to the right from this.
JSFiddle
HTML
<div id="wrapper">
<div id="test"><div id="fill"></div>
<div id="fill2"></div></div>
</div>
CSS
BODY{
background: url(http://farm6.staticflickr.com/5506/9699081016_ba090f1238_h.jpg) 0 -100px;}
#wrapper {
overflow: hidden;
height: 116px;}
#fill{
height: 40px;
position:absolute;
width:30px;
left:-30px;
background: #ccc;}
#fill2{
height: 40px;
position:absolute;
width:30px;
background: #ccc;
bottom:0;
left:-30px;}
#test {
height: 116px;
width: 692px;
background-color: #ccc;
position: relative;
float:right;}
#test:before {
content:"";
position: absolute;
top: 40px;
height: 50%;
width: 30px;
left: 0;
background-color: #ccc;
-webkit-transform: skew(40deg);
-moz-transform: skew(40deg);
-o-transform: skew(40deg);
-ms-transform: skew(40deg);
transform: skew(40deg);}
#test:after {
content:"";
position: absolute;
bottom: 40px;
height: 50%;
width: 30px;
left: 0;
background-color: #ccc;
-webkit-transform: skew(-40deg);
-moz-transform: skew(-40deg);
-o-transform: skew(-40deg);
-ms-transform: skew(-40deg);
transform: skew(-40deg);}

Rotating Image around y axis

I have an image which is divided into two equal parts. I am trying rotate the right part of the image in -180°(anti-clockwise) around y axis on hover.
Problem is some times(randomly) image gets rotated in 180°(clockwise) instead of -180°(anti-clockwise). what might be the reason behind this? I am using chrome.
css:-
.container {
position: relative;
margin-top : 10px;
width : 500px;
height: 330px;
-webkit-perspective: 1500px;
box-shadow: 3px 3px 13px #AAA;
}
.frontDiv {
padding: 20px;
width: 500px;
height: 330px;
}
.frontImg {
position: absolute;
border:1px solid;
height : 281px;
width : 225px;
overflow: hidden;
background-image: url('iday.jpg');
transition:all 1s ease-in-out;
-webkit-transition:all 1s ease-in-out;
backface-visibility : hidden;
-webkit-transform-origin:0% 0%;
}
.f1 {
top: 20px;
left:20px;
background-position: 0px 0px;
}
.f2 {
top: 20px;
left:245px;
background-position: -225px 0px;
}
.frontDiv:hover .f2
{
-webkit-transform : rotateY(-180deg);
}
html:-
<article class='container'>
<div class='frontDiv'>
<div class='frontImg f1'></div>
<div class='frontImg f2'></div>
</div>
</article>
fiddle
Some of the browsers are not supported rotate like,
Internet Explorer 9 (and earlier versions) and Opera does not support the rotateX or rotateY method.
else try
.frontDiv:hover .f2
{
transform: rotateY(-180deg);
-ms-transform: rotateY(-180deg); /* IE 9 */
-webkit-transform: rotateY(-180deg); /* Safari and Chrome */
}

CSS3 transform: rotateY a div to counter the rotateY of the parent

Can I transform: rotateY a div to counter the transform: rotateY of his parent ?
For example: if I have a parent div with rotateY(-45deg), all his childrens will be -45deg. Why can't I add rotateY(45deg) to the children to make it look like no rotation affected it?
Demo: http://jsfiddle.net/eBT4A/
You can add rotateY(45deg) to the children where parent div have rotateY(-45deg), to make it look like no rotation affected it only when you set same pivot point to these two rotation,
in your demo example you have not apply same pivot point,
Try this...
<html>
<head>
<style type="text/css">
body {
-webkit-perspective: 500;
}
#content {
position:absolute;
top: 0px;
left: 0px;
width: 300px;
height: 500px;
background: #000;
-webkit-transform-origin: 0px 0px;
-webkit-transform: rotate(45deg);
-moz-transform-origin: 0px 0px;
-moz-transform: rotate(45deg);
}
#element {
position:absolute;
top: 0px;
left: 0px;
width: 50px;
height: 50px;
background: #f00;
-webkit-transform-origin: 0px 0px;
-webkit-transform: rotate(-45deg);
-moz-transform-origin: 0px 0px;
-moz-transform: rotate(-45deg);
}
</style>
</head>
<body>
<div id="content">
<div id="element"></div>
</div>
</body>
</html>
You need to add preserve-3d to the parent:
body {
-webkit-perspective: 500;
}
#content {
position:fixed;
top: 20px;
left: 0;
width: 300px;
height: 500px;
background: #000;
-webkit-transform-origin: 0 0;
-webkit-transform: rotateY(45deg);
-webkit-transform-style: preserve-3d;
}
#element {
position:fixed;
top: 20px;
left: 50%;
width: 50px;
height: 50px;
background: #f00;
-webkit-transform-origin: 0 0;
-webkit-transform: rotateY(-45deg);
}
updated fiddle
As far as I know, that won't work in IE.

Resources