# Trigonometry in Sass

Have you ever found yourself needing trigonometric functions like sines, cosines and tangents when writing your Sass stylesheets? Ok, probably not, but the day may come, and you’ll be glad you read this.

Sass provides mathematical operators like addition and multiplication, and basic language constructs like conditionals and loops, but not much more. I’ve always relied on built-in methods, like `Math.sin`

and `Math.cos`

in JavaScript or Ruby, for these kinds of complex calculations…

Is there a way to approximate a sine or a cosine iteratively? It turns out there are plenty.

## Numerical methods#

If I had paid more attention in numerical analysis class, I may have been able to tell you everything about the CORDIC algorithm, the Chebyshev polynomials, or the Remez algorithm. But I didn’t, so the best I *can* do is to copy and paste the Taylor expansions for the sine and cosine functions:

Believe it or not, these equations give approximations that are good enough for our needs. So now we only have to translate them to Sass.

## Power#

Numerators $x^{(2n+1)}$ and $x^{(2n)}$ require an exponentiation operator, but we don’t have one in Sass, so we’ll have to implement our own *power* function:

Which could be translated into something like this:

```
@function pow($number, $exp) {
$value: 1;
@if $exp > 0 {
@for $i from 1 through $exp {
$value: $value * $number;
}
} @else if $exp < 0 {
@for $i from 1 through -$exp {
$value: $value / $number;
}
}
@return $value;
}
```

## Factorial#

Denominators $(2n+1)!$ and $(2n)!$ require us to implement a *factorial* function, but this is even more straightforward:

Which could look like this:

```
@function fact($number) {
$value: 1;
@if $number > 0 {
@for $i from 1 through $number {
$value: $value * $i;
}
}
@return $value;
}
```

## Sines, cosines and tangents#

Now we have all the necessary pieces to create our trigonometric functions, following the formulas of the Taylor expansions. Here we go:

```
@function pi() {
@return 3.14159265359;
}
@function rad($angle) {
$unit: unit($angle);
$unitless: $angle / ($angle * 0 + 1);
// If the angle has 'deg' as unit, convert to radians.
@if $unit == deg {
$unitless: $unitless / 180 * pi();
}
@return $unitless;
}
@function sin($angle) {
$sin: 0;
$angle: rad($angle);
// Iterate a bunch of times.
@for $i from 0 through 10 {
$sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1);
}
@return $sin;
}
@function cos($angle) {
$cos: 0;
$angle: rad($angle);
// Iterate a bunch of times.
@for $i from 0 through 10 {
$cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i);
}
@return $cos;
}
@function tan($angle) {
@return sin($angle) / cos($angle);
}
```

Let’s see if they work as expected:

```
@debug sin(pi() / 4); // => 0.70711
@debug cos(45deg); // => 0.70711
```

High fives all around!

## Alternatives#

If you are using Compass you already have plenty of math helpers at your disposal, so you don’t need to write your own.

If you are not using Compass, but you don’t mind getting your hands dirty and writing some Ruby code, you could extend the `Sass::Script::Functions`

module with whatever functions you want. To do that, create a file (e.g. `sass_math.rb`

) and paste the following contents:

```
require 'sass'
module Sass::Script::Functions
module CustomMath
def pi()
Sass::Script::Number.new(Math::PI)
end
Sass::Script::Functions.declare :pi, []
def sin(number)
trig(:sin, number)
end
Sass::Script::Functions.declare :sin, [:number]
def cos(number)
trig(:cos, number)
end
Sass::Script::Functions.declare :cos, [:number]
def tan(number)
trig(:tan, number)
end
Sass::Script::Functions.declare :tan, [:number]
private
def trig(operation, number)
if number.numerator_units == ['deg'] && number.denominator_units == []
Sass::Script::Number.new(Math.send(operation, Math::PI * number.value / 180))
else
Sass::Script::Number.new(Math.send(operation, number.value), number.numerator_units, number.denominator_units)
end
end
end
include CustomMath
end
```

What we are doing there is declaring the `pi`

, `sin`

, `cos`

and `tan`

functions so that they are accessible from our Sass stylesheets, and then delegating all the real work to the `Math.*`

functions in Ruby.

Let’s invoke the `sass`

command with our new file:

```
$ sass --require sass_math.rb input.scss output.css
```

Boom. It’s not as fun as writing your own functions, but it’s much more efficient.