I'm having difficulty figuring out how I could calculate the extra height of a div container caused by skewing it. I am masking an image inside the container and resizing it using a plugin.
The containers will not always have the same height and width so using fixed dimensions will not work.
Please see my demo. /
HTML
<div id="profiles" class="container">
<div class="profile">
<div class="image">
<img src="" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="" alt="">
</div>
<div class="detail">
</div>
</div>
</div>
CSS
#profiles {
margin-top: 300px;
transform:skewY(-30deg);
-ms-transform:skewY(-30deg); /* IE 9 */
-webkit-transform:skewY(-30deg); /* Safari and Chrome */
}
.profile {
cursor: pointer;
float: left;
width: 32.25%;
margin: 0.5%;
position: relative;
}
.profile .image {
position: relative;
overflow: hidden;
height: 400px;
background: #000;
backface-visibility:hidden;
-webkit-backface-visibility:hidden; /* Chrome and Safari */
-moz-backface-visibility:hidden; /* Firefox */
-ms-backface-visibility:hidden; /* Internet Explorer */
}
.profile .image * {
position: relative;
transform:skew(0deg,30deg);
-ms-transform:skew(0deg,30deg); /* IE 9 */
-webkit-transform:skew(0deg,30deg); /* Safari and Chrome */
}
I'm having difficulty figuring out how I could calculate the extra height of a div container caused by skewing it. I am masking an image inside the container and resizing it using a plugin.
The containers will not always have the same height and width so using fixed dimensions will not work.
Please see my demo. http://jsfiddle.net/RyU9W/6/
HTML
<div id="profiles" class="container">
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/1200" alt="">
</div>
<div class="detail">
</div>
</div>
</div>
CSS
#profiles {
margin-top: 300px;
transform:skewY(-30deg);
-ms-transform:skewY(-30deg); /* IE 9 */
-webkit-transform:skewY(-30deg); /* Safari and Chrome */
}
.profile {
cursor: pointer;
float: left;
width: 32.25%;
margin: 0.5%;
position: relative;
}
.profile .image {
position: relative;
overflow: hidden;
height: 400px;
background: #000;
backface-visibility:hidden;
-webkit-backface-visibility:hidden; /* Chrome and Safari */
-moz-backface-visibility:hidden; /* Firefox */
-ms-backface-visibility:hidden; /* Internet Explorer */
}
.profile .image * {
position: relative;
transform:skew(0deg,30deg);
-ms-transform:skew(0deg,30deg); /* IE 9 */
-webkit-transform:skew(0deg,30deg); /* Safari and Chrome */
}
Share
Improve this question
edited Jul 31, 2019 at 14:09
hyperdrive
asked Sep 6, 2013 at 17:34
hyperdrivehyperdrive
1,8465 gold badges21 silver badges36 bronze badges
5 Answers
Reset to default 8 In skew we have a case of Right-angled triangle and the skew new width is equal to "Opposite" and we've the angle and the opposite so by this equation we can get the adjacent Opposite = Adjacent * tan(angle); Where opposite in case of skewX is the div height and in case of skewY will be the div widthCheck this https://codepen.io/minaalfy/pen/exgvjb
function calculateSkew(){
var el = document.getElementById('bluebox');
var skewX = document.getElementById('skewX');
skewX.value = skewX.value || 0;
var skewY = document.getElementById('skewY');
skewY.value = skewY.value || 0;
var yRadians = skewY.value * Math.PI / 180;
var newHeight = el.offsetWidth * Math.tan(yRadians);
var calculatedHeight = el.offsetHeight + newHeight;
var xRadians = skewX.value * Math.PI / 180;
var newWidth = calculatedHeight * Math.tan(xRadians);
var calculatedWidth = el.offsetWidth + newWidth;
el.style.transform = ("skewX(" + skewX.value + "deg ) skewY(" + skewY.value + "deg )");
var output = document.getElementById('output');
output.innerHTML = "skewY by "+skewY.value+ " and new height calculated is "+calculatedHeight+ "<br> skewX by "+skewX.value+ " and the new calculated width is "+ calculatedWidth;
}
body {text-align:center}
#bluebox {width:100px;height:100px;background:blue;margin: 20px auto;}
<h4>Enter any numeric value for skewX or skewY to calculate the new width&height for the box</h4>
<div id="bluebox"></div>
<input type="number" placeholder="skewX" id="skewX" onkeyup="calculateSkew()" />
<input type="number" placeholder="skewY" id="skewY" onkeyup="calculateSkew()" />
<h1 id="output"></h1>
I got it using this solution.
var degrees = 30;
var radians= degrees*Math.PI/180;
var newHeight = parentWidth*Math.tan(radians);
var newOffset = newHeight / 2;
var parentHeight = parentHeight + newHeight;
Here is my updated fiddle with option to select degrees
http://jsfiddle.net/bhPcn/5/
Two functions that could help you.
function matrixToArray(matrix) {
return matrix.substr(7, matrix.length - 8).split(', ');
}
function getAdjustedHeight(skewedObj){
var jqElement = $(skewedObj);
var origWidth= jqElement.width();
var origHeight= jqElement.height();
var matrix = matrixToArray(jqElement.css('transform'))
var alpha = matrix[2];
var adjusted = Math.sin(alpha)*origWidth/Math.sin(Math.PI/2-alpha);
return origHeight+Math.abs(adjusted);
}
function getAdjustedWidth(skewedObj){
var jqElement = $(skewedObj);
var origWidth= jqElement.width();
var origHeight= jqElement.height();
var matrix = matrixToArray(jqElement.css('transform'))
var alpha = matrix[1];
var adjusted = Math.sin(alpha)*origHeight/Math.sin(Math.PI/2-alpha);
return origWidth+Math.abs(adjusted);
}
Usage (http://jsfiddle.net/x5her/18/):
// if you use scewY
console.log(getAdjustedWidth($(".image")[0]))
// if you use scewX
console.log(getAdjustedHeight($(".image")[0]))
Example of dynamic skew
angle depending on the height.
In angular:
// We use a mathematical expression to define the degree required in skew method
// The angle depend on the height and width of the container
// We turn the answer from atan which is in radian into degrees
//
// DEGREES = RADIAN * 180 / PI
const degrees = Math.atan(
parent.nativeElement.clientWidth / parent.nativeElement.clientHeight
) * 180 / Math.PI;
parent.nativeElement.children[0].style.transform = `skew(${degrees}deg)`;
parent.nativeElement.children[1].style.transform = `skew(${degrees}deg)`;
In Jquery for the snippet :
$(document).ready(() => {
const parent = $('.duo:first');
const degrees = Math.atan(parent.width() / parent.height()) * 180 / Math.PI;
$('.first').css('transform', `skew(${degrees}deg)`);
$('.second').css('transform', `skew(${degrees}deg)`);
});
.container {
width: 10em;
height: 10em;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.one-square {
height: 100%;
width: 0;
flex-grow: 1;
display: flex;
}
.duo {
height: 100%;
width: 0;
flex-grow: 1;
display: flex;
flex-direction: row;
position: relative;
overflow: hidden;
}
.first {
width: 100%;
height: 100%;
background-color: red;
transform: skew(0deg);
transform-origin: 0 0;
position: absolute;
}
.second {
width: 100%;
height: 100%;
background-color: yellow;
transform: skew(0deg);
transform-origin: 100% 100%;
position: absolute;
}
.a {
background-color: grey;
}
.b {
background-color: green;
}
.c {
background-color: lightgrey;
}
.d {
background-color: #444444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="one-square a"></div>
<div class="one-square b"></div>
<div class="duo">
<div class="first">
</div>
<div class="second">
</div>
</div>
<div class="one-square c"></div>
<div class="one-square d"></div>
</div>
Now that it's 2021, just use el.getBoundingClientRect().height
. It takes css transform into its calculations.