css skew element and keep max-width

58 Views Asked by At

If I distort a container with the skew property, then the short corners are inside the original dimensions and the long corners are outside. This can be seen in diagram 1 with the blue box.

diagram 1 :

However, I would like the outer corners not to exceed the original width, as in diagram 2 with the red box.

diagram 2 :

I could basically solve this with margin, but the protruding width depends on the length of the container.

Is there a way not to exceed the original width?

I have tried to work with margin, but since the height of the box is not known, I cannot calculate the margin

1

There are 1 best solutions below

0
Tom On

Pure CSS

If the height and width of the container div are known, you could try something like this, utilising the formula 'a = b x tan(α)' for finding the additional length after the skew and subtracting it from the overall width of the div.

This source can better explain the math if you're unfamiliar with it.

You can adjust the width variable in the code snippet to see it work.

body {
  --height: 80px;
  --width: 120px;
  --skew: 20deg;
}

div {
  background-color: skyblue;
  width: var(--width);
  height: var(--height);
  display: flex;
  justify-content: center;
}

.skewed {
  transform: skew(var(--skew));
  background-color: pink;
  height: var(--height);
  
  /* container width - (height x tan(skew)) */
  width: calc(var(--width) - (var(--height) * tan(var(--skew))));
}
<div>
  <div class="skewed"></div>
</div>

JavaScript

If the height and width values of the container are not known, you can retrieve them using JavaScript and use the same calculation to set the width of the child element.

Be aware that Math.tan() uses radians instead of degrees so a conversion is required if you're also using degrees.

var container = document.getElementById('container');
var positionInfo = container.getBoundingClientRect();

var height = positionInfo.height;
var width = positionInfo.width;

var child = document.getElementById('skewed');

/* same calculation but converting radians to degrees */
child.style.width = (width - (height * Math.tan((20 * Math.PI) / 180))) + "px";
body {
  --height: 80px;
  --width: 120px;
  --skew: 20deg;
}

#container {
  background-color: skyblue;
  width: var(--width);
  height: var(--height);
  display: flex;
  justify-content: center;
}

#skewed {
  transform: skew(20deg);
  background-color: pink;
}
<div id="container">
  <div id="skewed"></div>
</div>