Reputation: 2707
I have a ::before
element that is the same size as the parent element, but rotated slightly. It is used in a number of places and the height of the parent element varies depending on content.
The problem I am having is that using (for example) transform: rotate(-1deg);
is not enough rotation for small elements and far too much for large elements.
Here is a jsfiddle example (snippet below) - hover over the blue box to see what happens to the orange box when the blue box is taller.
.container {
width : 26px;
border : 1px solid #999;
display : flex;
justify-content : center;
margin : 0 auto;
padding : 3px 0;
}
.box {
height : 60px;
width : 20px;
background : blue;
position : relative;
transition : height 1s ease-in-out;
}
.box:hover {
height :400px;
}
.box::before {
content : "";
position : absolute;
height : 99%;
width : 99%;
background-color : orange;
left : 0px;
top : -1px;
transform : rotate(-3deg);
z-index : -1;
transform-origin : center center;
}
<div class='container'>
<div class='box'> </div>
</div>
How can I counter this effect such that instead of the number of degrees rotation being the constant, the pixel width from top left of the ::before and top left of the parent element is (roughly) constant? I don't need it to be exact, just not crazy when the content makes the parent element very tall.
I am trying to determine if there is a css only solution. I can figure out a way to do it with js by simply changing the rotation degrees to a number calculated based on the parent element height after content is inserted.
Alternative version, left is correct, middle is incorrect, right is correct. The heights are not defined and may change dynamically. https://jsfiddle.net/4x6qdtv7/
.container {
float: left;
width: 26px;
border: 1px solid #999;
display: flex;
justify-content: center;
margin-right: 10px;
padding: 3px 0;
}
.c1 .box {
height: 60px;
}
.c2 .box {
height: 400px;
}
.c3 .box {
height: 400px;
}
.box {
height: 60px;
width: 20px;
background: blue;
position: relative;
}
.box:hover {
height:400px;
}
.c1 .box::before, .c2 .box::before {
transform: rotate(-3deg);
}
.c3 .box::before {
transform: rotate(-.4deg);
}
.box::before {
content: "";
position: absolute;
height: 99%;
width: 99%;
background-color: orange;
left: 0px;
top: -1px;
z-index: -1;
transform-origin: center center;
}
<div class='container c1'>
<div class='box'> </div>
</div>
<div class='container c2'>
<div class='box'> </div>
</div>
<div class='container c3'>
<div class='box'> </div>
</div>
Upvotes: 0
Views: 299
Reputation: 22310
when answering I saw Temani Afif answer so I hesitated.
Now I tell myself that this answer can still be of interest (and it is much simpler).
It also shows how to calculate with different units
.container {
float : left;
width : 26px;
border : 1px solid #999;
display : flex;
justify-content : center;
margin-right : 10px;
padding : 3px 0;
--clr : orange;
}
.container:hover {
--clr : yellow;
}
.c1 .box { --hgt : 100; }
.c2 .box { --hgt : 200; }
.c3 .box { --hgt : 400; }
.c1:hover .box { --hgt : 200; }
.c2:hover .box { --hgt : 400; }
.c3:hover .box { --hgt : 100; }
.box {
height : calc(1px * var(--hgt));
width : 20px;
background : blue;
position : relative;
transition : height 1s ease-in-out;
}
.box::before {
content : "";
position : absolute;
height : 100%;
width : 99%;
background-color : var(--clr);
left : 0;
top : -1px;
transform : rotate( calc(-500deg / var(--hgt))); /* adjust 500deg */
z-index : -1;
transform-origin : center center;
}
<div class='container c1'>
<div class='box'></div>
</div>
<div class='container c2'>
<div class='box'> </div>
</div>
<div class='container c3'>
<div class='box'> </div>
</div>
Upvotes: 0
Reputation: 272842
You can approximate this differently using clip-path
. Resize the main container to see the result:
.box {
--d:15px; /*adjust this */
width:100px;
height:200px;
border:1px solid red;
padding:15px; /* this */
position:relative;
z-index:0;
overflow:hidden;
resize:both;
}
.box div{
height:100%;
background:blue;
}
.box::before {
content:"";
position:absolute;
margin:5px; /* and this */
top:0;
left:0;
right:0;
bottom:0;
z-index:-1;
background:green;
clip-path:polygon(0 var(--d),calc(100% - var(--d)) 0,100% calc(100% - var(--d)),var(--d) 100%);
}
<div class="box">
<div></div>
</div>
Upvotes: 2