Jason Axelrod Jason Axelrod - 3 months ago 8
CSS Question

Calculate position by degrees in CSS?

Okay, this question is a bit math, a bit CSS help... Lets say I have a polygon:



:root {
--poly-height: 100px;
--poly-width: 300px;
}

.poly1 {
background-color: black;
height: var(--poly-height);
width: var(--poly-width);
-webkit-clip-path: polygon(
0 0,
30px 100%,
100% 100%,
calc(100% - 20px) 50%,
100% 0
);
}

<div class="poly1">&nbsp;</div>





This polygon has FIVE points, lets call them
A
B
C
D
E
.

If we look at point
B
, you can see the
x,y
position is
30px 100%
. This leads to a slant of I don't know how many degrees...

Now lets say, some time in the future, I want to change the height of the
.poly1
element. However, changing the height of the element will also change the degrees of the slant since the 30px inset is set in stone.

What I would like to know, is if there is a way to calculate for the value of the inset, knowing the height of the element, the starting point of
0,0
, and a desired degree of slant, lets say 20deg... and can this be done in a CSS calc?

So starting from point
A
of
0,0
, I would like to get the
x
value of point
B
, desiring a 20deg slant, and knowing what the value of
y
is going to be. In the example above, it is set to
100px
;


  • EDIT *



Searching online, I have found out that the math calculation for this would be:

y = height * tan(20 degrees)


Now... is it possible to do this in a CSS3 calc?

Answer

CSS cannot do this on its own with the syntax tan you're suggesting. Even pre-processor languages such as Sass/SCSS don't have built-in trigonometric functions.

You definitely need a CSS3 variable (--polygon-height) if you want to be able to change it only in one place (or use a pre-processor). You can then use var() to get the value of the variable where needed and calc to approximate the tan value.

Taylor series

Taylor series is some very awesome stuff. This is how computers under the hood probably calculate complex stuff such as trigonometric functions which you need.

Here's how you calculate tangent.

Tangent power series

Note that the formula uses radians and not degrees. Also note that this is an approximation and might or might not work for ou depending on the angle size and the precision you desire. Search online for more terms if you need them.

Implementation

Now we can use calc because we just need simple addition and multiplication. We don't have powers so we need to multiply mulitple times.

:root {
  --poly-height: 100px;
  --poly-width: 300px;
  --poly-degree: calc(20 * 0.0174533); /* degree to radian */ 
}

.poly1 {
  background-color: black;
  height: var(--poly-height);
  width: var(--poly-width);
  -webkit-clip-path: polygon(
    0 0,
    calc(var(--poly-height) * (var(--poly-degree) + (1/3) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) + (2 / 15) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) + (17/315) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree))) 100%,
    100% 100%,
    calc(100% - 20px) 50%,
    100% 0
  );
}
<div class="poly1">&nbsp;</div>

Example

Here's what happens if we change some stuff.

:root {
      --poly-height: 200px;
      --poly-width: 300px;
      --poly-degree: calc(45 * 0.0174533);
    }

    .poly1 {
      background-color: black;
      height: var(--poly-height);
      width: var(--poly-width);
      -webkit-clip-path: polygon(
        0 0,
        calc(var(--poly-height) * (var(--poly-degree) + (1/3) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) + (2 / 15) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) + (17/315) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree) * var(--poly-degree))) 100%,
        100% 100%,
        calc(100% - 20px) 50%,
        100% 0
      );
    }
Height: 200px, degree: 45deg
<div class="poly1">&nbsp;</div>