Skip to content

Instantly share code, notes, and snippets.

@stereokai
Created June 18, 2017 11:03
Show Gist options
  • Save stereokai/7666bfe93929b14c2dced148c79e0e97 to your computer and use it in GitHub Desktop.
Save stereokai/7666bfe93929b14c2dced148c79e0e97 to your computer and use it in GitHub Desktop.
Trigonometry in CSS
//----------------------------------*\
// TRIGONOMETRY FUNCTIONS
//----------------------------------*/
// # Trigonometry in CSS
//
// - Through Taylor/Maclaurin polynomial representation: http://people.math.sc.edu/girardi/m142/handouts/10sTaylorPolySeries.pdf
// - Useful if you don't want to use JS.
// - With CSS Variables.
// - `calc()` can't do power (x ^ y) so I used multiplication instead.
// `--angle` is in radians! Convert from degrees using `α * π / 180` (or `α * 0.01745329251`) :)
// Sine function representation
.sin {
--sin-term1: var(--angle);
--sin-term2: calc((var(--angle) * var(--angle) * var(--angle)) / 6);
--sin-term3: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 120);
--sin-term4: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 5040);
--sin-term5: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 362880);
--sin: calc(var(--sin-term1) - var(--sin-term2) + var(--sin-term3) - var(--sin-term4) + var(--sin-term5));
}
// Cosine function representation
.cos {
--cos-term1: 1;
--cos-term2: calc((var(--angle) * var(--angle)) / 2);
--cos-term3: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 24);
--cos-term4: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 720);
--cos-term5: calc((var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle)) / 40320);
--cos: calc(var(--cos-term1) - var(--cos-term2) + var(--cos-term3) - var(--cos-term4) + var(--cos-term5));
}
// Tangent function representation
.tan {
--tan-term1: var(--angle);
--tan-term2: calc((1/3) * var(--angle) * var(--angle) * var(--angle));
--tan-term3: calc((2 / 15) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle));
--tan-term4: calc((17/315) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle) * var(--angle));
--tan: calc(var(--tan-term1) + var(--tan-term2) + var(--tan-term3) + var(--tan-term4));
}
@r3dvorak
Copy link

r3dvorak commented Jul 21, 2019

Hi,
how can I use this, if I don't have an angle but only the length of side a and side b ?
(the original PDF is not available any longer)

Thanks,
Richard

@stereokai
Copy link
Author

You will have to modify these formulas to α = sin ^ -1 * (sideA / sideB) (or the equivalents of tan and cos, depending on which sides you have - see here)

@ffoodd
Copy link

ffoodd commented Aug 12, 2019

FYI @stereokai I’m using you SIN calculation to draw some charts with CSS :)
Here is some demo page (in French for now) → https://ffoodd.github.io/chaarts/pie-charts.html
You're credited both in source code and in details, below first chart.

Thanks a lot for this!

@stereokai
Copy link
Author

@ffoodd that looks amazing! What a great job! I love your implementation :)

@smrghsh
Copy link

smrghsh commented Dec 9, 2020

@stereokai this is incredible and made my day!!!!

@Alynva
Copy link

Alynva commented Apr 5, 2021

Awesome snippet!

I've needed a bigger range (with 4 terms this formula works best between -2pi and 2pi), so I made this generator: https://codepen.io/Alynva/full/gOgWqQm

I found that using the Taylor Series, you can go up to 86 terms for calculating the sine and 87 for the cosine, covering a range of -10pi to 10pi. This limit is due to JavaScript casting the numbers to Infinity

@stereokai
Copy link
Author

@Alynva that's pretty dope! Well done!

@vintprox
Copy link

vintprox commented Jun 9, 2021

Woo, you can do wonders with this ☺️

@richstokes129
Copy link

This works great! Thanks!

@JiveDig
Copy link

JiveDig commented Mar 18, 2022

This looks interesting but trig is a little over my head. Can this be used to calculate the distance between the top of the container when using transform: skew(3deg);?

If we know the angle is 3 degrees, and the distance is 100vw, can this snippet help me figure out the gap it in the screenshot? Thanks :)

image

@Alynva
Copy link

Alynva commented Mar 18, 2022

This looks interesting but trig is a little over my head. Can this be used to calculate the distance between the top of the container when using transform: skew(3deg);?

If we know the angle is 3 degrees, and the distance is 100vw, can this snippet help me figure out the gap it in the screenshot? Thanks :)

Sure @JiveDig ! Here it is: https://codepen.io/Alynva/pen/ZEvQmPv

If you want to use it in different elements (nav height and hero background transform), calculate the variables in the parent and apply them in the children properties.

@JiveDig
Copy link

JiveDig commented Mar 18, 2022

@Alynva Wow super cool! Thanks so much for the example, it helped tremendously. I also just remembered I can do transform-origin: top left; then I only need to manage the overlap at the bottom. I very much appreciate your help. Thanks again!

@Alynva
Copy link

Alynva commented Mar 18, 2022

@JiveDig yes, if you just need the offset in the same element, transform-origin can do the job easily. Just in other contexts where you change multiple elements that you actually need to calculate it

@JiveDig
Copy link

JiveDig commented Mar 18, 2022

For sure. I'll definitely need it. Super powerful stuff :)

@r3dvorak
Copy link

Playing with Alynva's codepen examples, but can't quite figure out what I need. Please check this out:
RDexample
The Opposite side has a fixed height of 104 px, Adjacent side is 100% or 100vw of the browser window, the tip of the angle x needs to stay fixed to the right side and therefore I need to calculate the angle x.
IE, a browser window width of 960px will calc to TAN x = O/A = 104/960 = 0,108333, tan^-1 of 0,108333 = 6.182930°

@Alynva
Copy link

Alynva commented Jan 19, 2023

@r3dvorak that might not work, because every value has the unit measurement with it, and the calc doesn't quite work when you mix then expecting the result be in one unit. You probably will get some result if you doesn't use units (and consequently fixed values), then in the last step you can "cast" the unit by multiplying the value by 1[unit], like calc(1px * 100).

Here is my attempt to do what you want: https://codepen.io/Alynva/pen/gOjXJyW

But for values greater than 1 (in rad)(45º), the approximation of the arctan gets worse. I don't know if I coded the original generator right to get the arctan approximation, as far I tested, with more terms it gets worse (???). If you spot something wrong in the code I can fix it: https://codepen.io/Alynva/pen/gOgWqQm I read some books and thats exactlly what should happen, with that formula:

image

So, I think that the code is correct.

@r3dvorak
Copy link

r3dvorak commented Jan 19, 2023

Thanks! I'll check that out.
The 100vw was just for demonstration purposes - it will be given in px, taken from the browser window width at that moment. Maybe easier to see what I mean here: https://www.franzk.net
Resize the window - of course, this site just mimics the behavior I want, using a partially white PNG sliver bg and a lot of media queries to adjust the modules below ;). It would be cool to adjust the angle of the whole header and the modules below the header dynamically.
Besides the jumping when resizing the window, the biggest problem is that my header is a rectangle, and so there are parts on the right, underneath it, that are visible but not clickable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment