Note: This question is about a problem with output, and not about creation of any shape.
I recently created a shape :
By way of a revision of my initial answer which produced an output rather than an explanation, I would postulate* that the effect is seen because you are surmising a negative skew can be used to offset a position on the positive skew curve, when in fact- at minus values you are operating on the negative skew curve.
This would first require that the measure of skew was singular and occurring on the same curve (see normal curve below), with positive and negative values allowing to shift along the curve.
However, the curve for negative and positive skews are inversly tailed.
Zero skew is the only value which operates the same on both. As such, if you have an element, apply a skew of 20 degrees to it, then apply a skew of minus 20 you will actually have a skew (positive or negative) of zero, so using a negative offset appears to work..
However, if you then apply additional negative skew, you will have a negatively skewed element, the curve for which is different and not equal to the inverse equivalent position on the positive skew curve.
20deg = Original element, 20deg on positive skew curve
20deg - 20deg = 0, same for positive and negative skew curve
-40deg = taking the elements current 20deg skew, minus 40 deg = 20deg on negative skew curve - NOT an equivalent 'opposite' point on the positive skew curve
When using psuedos, the skew works because you arent offsetting a positively skewed value by a newgatively skewed amount.
* Im no mathematician, so afraid I can only claim this as conjecture
I will just address to the main issue, as to why it happens, instead of trying to provide alternatives
Since your math appears to be exact, we have to search for what is not exact, which is the platform itself...
MDN's article on transform states that it is not a stable technology:
This is an experimental technology
Because this technology's specification has not stabilized, check the
(emphasis mine)
Consider the following:
When you skew the main div, it requires a huge amount of browser render calculations to show in a 2D environment what it would look like considering both 3 axis... The pseudo element suffer with those calculations, as you can see if you further it a little left from the edge where you've put it:
See that I just moved to the left, and that caused it to go down a little, according to the Y skewing applied to the main div. Now, add to that another huge amount of calculations when you re-skew the pseudo element... The browser will just fail to provide an accurate render of what the 3D space would look like in a 2D environment...
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)
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 :