From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.

In part 1 we got an overview of trigonometry and learnt how we can use trigonometric functions in Sass. But for dynamic variables, we would be wise to move our calculations into JavaScript. Let’s take a look at an example that’s slightly more complex than clipping a simple triangle.

This article is the 2nd part in a series on “Trigonometry in CSS and JavaScript”:

- Introduction to Trigonometry
**Getting Creative with Trigonometric Functions**(this article)- Beyond Triangles

In the following demo we have a square-based pyramid, built with CSS 3D transforms. Using the slider, we can change the length of the sides of the pyramid, which results in changes to the overall height, and the angle of the sloping sides.

See the Pen Pyramids by Michelle Barker (@michellebarker) on CodePen.

To recalculate the angle at which the sides are rotated every time the input value changes, we need trigonometry. In order to do that, we can take a cross-section of the pyramid from the side, and visualize it as a triangle.

We can see that, just like our equilateral triangle in the previous article, the cross-section of our pyramid can be broken up into two right-angled triangles. (This time the shape of the cross-section is an isosceles triangle — a triangle that has two sides of equal length.)

To create the shapes for the base and sides of the pyramid, we can set the width and initial height, and use `clip-path`

to clip the triangular shape of the sides.

```
.shape__base {
--w: 10rem;
width: var(--w);
height: var(--w);
}
.shape__side {
width: var(--side);
height: var(--h, 20rem);
clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
```

I’m using custom properties here because they allow us to easily reuse identical values. I’m setting a default value for the `--h`

custom property for the `height`

value of the shape side, as we’ll change this value later on with JavaScript. (This is the value we’ll get from the slider.)

Going back to our cross-section diagram, we can see that our *known* values are the *opposite* side (which will be half of our `--w`

variable) and the *hypotenuse* (the `--h`

variable). What is *unknown* is the angle at which we need to rotate the sides so that they meet in the middle.

If we imagine the side of the pyramid originates from a starting position in the center, the angle we need to calculate is the one at the top of the triangle. We can think of it as being a bit like leaning a ladder against a wall. The angle between the ladder and the wall is the one we need to calculate.

Again, we can use custom properties in our CSS to set some transform values. Each side will have the same `rotateX()`

value (the angle we’re going to calculate), but different `rotateY()`

values, as they’ll be rotated around the pyramid (represented by the `--ry`

custom property here):

```
.shape__side {
transform-origin: top center;
transform:
rotateY(var(--ry, 0))
rotateX(var(--angle, 15deg));
}
.shape__side:nth-child(2) {
--ry: 90deg;
}
.shape__side:nth-child(3) {
--ry: -90deg;
}
.shape__side:nth-child(4) {
--ry: 180deg;
}
```

## Calculating angles

In the previous article we saw how we can calculate the length of any side of a right-angled triangle if we know the angle, but how about calculating the angle itself? For that, we need to rearrange our equations.

We know the *opposite* side and the *hypotenuse*, which indicates we need to use the *Sine* function. Dividing the *opposite* by the *hypotenuse* gives us *sin(ϴ)*:

`sin(angle) = o / h`

Therefore the angle is calculated by the inverse *Sine* (or *Arcsine*) of the *opposite* divided by the *hypotenuse*:

## Math functions

We can use JavaScript math functions for this. Let’s create a function to call whenever the input changes, and update the `--h`

(for the *hypotenuse*) and `--angle`

custom properties. To get the *Arcsine* value we use `Math.asin()`

:

```
const shape = document.querySelector('.shape')
const input = document.querySelector('[data-slider]')
const setAngles = () => {
const o = shape.clientWidth / 2
const h = input.value
const angle = Math.asin(o / h)
shape.style.setProperty('--h', `${h}px`)
shape.style.setProperty('--angle', `${angle}rad`)
}
input.addEventListener('input', setAngles)
```

### Radians versus degrees

You might notice that we’re setting the `--angle`

custom property value in radians, not degrees. Unless you’re a mathematician, there’s a good chance you usually think of angles in terms of degrees, rather than radians. A radian can be visualized as the length of the radius of a circle wrapped around the circumference. There are 2pi radians in a circle.

The `Math.asin()`

function gives us the angle in radians, and radians are perfectly legitimate units in CSS, so this will work just fine. But if you prefer to set the value in degrees, we can convert them with a simple function:

```
const radToDeg = (radians) => {
return radians * (180 / Math.PI)
}
```

In the demo I’m also rounding the resulting value to two decimal places with `toFixed()`

:

```
const setAngles = () => {
const o = shape.clientWidth / 2
const h = input.value
const radians = Math.asin(o / h)
const angle = radToDeg(radians).toFixed(2)
shape.style.setProperty('--h', `${h}px`)
shape.style.setProperty('--angle', `${angle}deg`)
}
```

Now the angles of the sides of our pyramid will be recalculated every time we move the slider to change the length of the sides.

## Get creative

Using the same method, we could even create a bunch of pyramids of random heights, by changing a single custom property:

See the Pen Pyramids by Michelle Barker (@michellebarker) on CodePen.

Here’s another creative example of trigonometry in action: A paper snowflake maker, where the user can drag the handles to clip out segments of a triangle to generate the snowflake pattern. The clip path coordinates were calculated using trigonometric functions.

See the Pen Snowflakes with clip-path trigonometry by Michelle Barker (@michellebarker) on CodePen.

In the next article we’ll see how trigonometry affords us even more creative possibilities when combined with JS, by enabling us to plot polygons and more complex shapes.