Note: This question is about a problem with output, and not about creation of any shape.
I recently created a shape :
.prog {
position: relative;
top: 20px;
width: 150px;
height: 120px;
background: green;
display: inline-block;
transform: skewY(20deg);
transform-origin: 0% 100%;
transition: 0.8s ease;
}
.prog:before {
content: "";
position: absolute;
left: 150px;
width: 150px;
height: 120px;
background: red;
transform: skewY(-40deg);
transform-origin: 0% 100%;
transition: 0.8s ease;
}
<div class="prog "></div>
In the above snippet, the green shape is the .prog
element, and is skewed. The red shape is :before
pseudoelement of the first element.
I skewed .prog
(skewY) to 20deg. Now, I needed :before
to be -20deg. For this, I first had to unskew it. Then skew it further 20deg.
So final skewY
value will be -40deg. I applied this, and appropriate transform-origin
s.
But the problem is that the top points of both the shapes aren't aligning. They should, but they aren't. Here's an image showing the problem :
The black lines are just for reference.
Now even more!
I skewed -20
-20
instead of -40
:
transform: skewY(-20deg) skewY(-20deg);
<--
This works!transform: skewY(-40deg);
<----------------
This doesn't!
The behaviour of the "unskewed" child is normal, it is the way skew works. In order to understand this, I am going to simplify the question to :
why isn't
skewX(40deg)
the same asskewX(20deg) skewX(20deg)
?
div {
width: 100px; height: 100px;
position:absolute;
top:20px; left:20px;
transform-origin: 0 0;
}
.d1 {
transform: skewX(40deg);
background: red;
opacity:0.7;
}
.d2 {
transform: skewX(20deg) skewX(20deg);
background: blue;
opacity:0.7;
}
/** FOR THE DEMO **/
body {background: url('http://i.stack.imgur.com/GySvQ.png');background-size: 10px;}
.m {text-align:right;padding-top:105px;}
.m1{width:83px;color:red;border-right:1px solid red;}
.m2 {width:72px;color:blue;border-right:1px solid blue;}
p{margin:0 0 5px 150px;color:red;}
.b{color:blue;}
<div class="d1"></div>
<div class="d2"></div>
<div class="m m1">x = 83</div>
<div class="m m2"><br/>x = 72</div>
<p class="r">skewX(40deg)</p>
<p class="b">skewX(20deg) skewX(20deg)</p>
Note: for the sake of explanation I will be using a 100*100
square div and the transform origin is set on the top left corner of this div. Like in the above code snippet.
To understand the difference between the two transformations, we need to explore the way the CSS skew() function works. The specs say :
A 2D skew transformation along the X axis with the parameter alpha is equivalent to the matrix:
So this means we can calculate the coordinates of each point of a 2D X skewed element like this :
| 1 tan(α) | . | x |
| 0 1 | | y |
x/y
the coordinates of the point before transformationFor skewX(40deg)
α = tan(40deg) ~= 0.83
| 1 0.83 | . | 0 | | 83 |
| 0 1 | | 100 | = | 100 |
The new coordinates are x = 83
as seen in the code snippet example.
For skewX(20deg) skewX(20deg)
α = tan(20deg) ~= 0.36
first skew :
| 1 0.36 | . | 0 | | 36 |
| 0 1 | | 100 | = | 100 |
Second skew :
| 1 0.36 | . | 36 | | 72 |
| 0 1 | | 100 | = | 100 |
The new coordinates are x = 72
as seen in the code snippet.
Both transformations don't give the same result. So skewY(20deg) skewY(-40deg)
isn't the same transformation as skewY(-20deg)
and the two top corners of the red and green elements can't align as :
tan(20deg) != tan(40deg)/2
References :
skew introduces a vertical offset equal to the tangent of the angle. So, skew(20deg) introduces an offset of tan(20deg).
For your example to work, it should be that
tan(-20deg) = tan(20deg) + tan( -2 * 20deg)
or
tan (2 * x) = 2 * tan (x)
but this is not true, tangent and sum are not asociative
the required skew to reverse it is
result = - atan ( 2 * tan (x))
that, for x = 20, gives a result of
36,052388732387908475278040193987
(aproximately)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With