Math Functions
Let me tell you a secret. Throughout this course, you’ve already seen that CSS has many functions. Any time a syntax involved parentheses (()
), you were calling some built-in CSS function.
For example, you might remember the chapter on gradients (linear-gradient(...)
) or grids (repeat(...)
). And maybe you already figured out that using variables (var(...)
) is also a function!
A function is nothing more than something that requires input (the numbers or values that you put in), executes some predictable action with it, then gives you the output (the end result).
For example, the linear-gradient()
function requires those “color stops” as input, then transforms them and outputs the actual gradient image.
Functions can accept any input, so also the output of another function. You can nest functions within functions as much as you want—though that’s obviously not recommended for readability.
Anything remotely complex (both in programming and in the real world, actually) will be described by a function of some sort. CSS is no different. If you want to achieve something complicated, chances are that there’s some obscure function that will do exactly what you want. (If you spend some time crawling through the docs.)
This chapter, therefore, only explains the most common and useful math functions. Other functions are explained in the chapter where they belong (as you know now) or left behind.
Why do I need math? I thought we were designing! These functions are mostly useful for responsive design. They allow you to easily adapt to different screen sizes or box dimensions, by calculating values in a smart way. They also help implement fail-safes (or thresholds) against ugly situations you never want to happen in your design.
Though some of them are surely just fun additions to add spice to a creative design, instead of a crucial CSS feature.
Calc
The calc()
function allows you to perform any calculation on multiple values. This is often used to …
- Combine different values with different units (which you somehow can’t fix by getting your units straight).
- Undo or add extra spacing you do not want.
Maybe the padding/margin pushes an element to be just a little wider than the screen, even though you set width: 100%
. You can compensate for this space you don’t want with calc
.
The example below shows this as well. See what happens when you just set left: 100%
. It pushes the circle out of frame, because the “origin” of CSS boxes is at the top left. So if we truly want the circle pushed to the right edge, we need to compensate.
Of course, this is a contrived example. In this specific case, you’d just do right: 0;
instead/
In Practice: scaling font size
I’ll explain a great practical application that almost all my websites use.
A common issue with responsive design is font size. Text is most readable when the width of each line is around 50 to 75 characters. Too wide and it becomes an overwhelming wall of text. Too short and it just becomes a column of words underneath each other.
So … how do we make sure our text has a nice size regardless of the user’s screen size?
By implementing a simple calculation that automatically resizes our text.
The text never becomes smaller than 15px
, which is a nice baseline for readability. But the wider the screen gets, the bigger the font becomes.
If you set this property and then use relative units (em
, rem
, %
) throughout, you’re already 90% towards a completely responsive design.
This isn’t mine. I found this online a long time ago and have learned it’s the holy grail ever since ;)
Min/Max
Like my example above, you often want values to be responsive, but to stick within their lane. Font size should never become too big or too small. An element’s width should dynamically resize, but never become too small.
These two functions help to set nice boundaries for your values.
- The
min(value, value, ...)
function outputs the lowest of all values. - The
max(value, value, ...)
function outputs the highest of all values.
You can supply as many values as you want, as long as they’re separated by a comma (,
).
The example below shows a font size that automatically scales (with viewport width), but never goes outside the range of 14px
to 20px
. To test this, resize your own browser window to resize the examples.
Clamp
The example above has a faster way to write it: the clamp(min, val, max)
function. As expected, it clamps a value between two boundaries, never allowing it to go lower or higher than that.
Round
Near the start, I mentioned how relative units can have an issue with sharpness. If their number ends up being 14.5px
(for example), then the browser doesn’t know what to do. How could it display half a pixel? So you might end up with blurriness or unexpected behavior.
The round(val)
function can help with that. It rounds the input to the nearest whole integer.
It also allows styling things in “steps” or “levels”, instead of a smooth transition.
It also allows a second argument that determines how the rounding happens. (You can also round to the nearest multiple of 10, for example.)
At the time of writing (late 2023), this isn’t implemented anywhere yet. But I expect that to be the case relatively soon, and I think it’s a useful function, which is why I mention it.
Abs & Sign
These two functions help deal with (potentially) negative numbers. Those are usually bad, because almost all CSS values (dimensions, lengths, time) should always be positive—otherwise they don’t make sense.
- The
abs(val)
function returns the absolute value of its input. What’s that? If the number is negative, it removes the minus sign. - The
sign(val)
function returns 1 for positive numbers and -1 for negative numbers. (And 0 for 0.)
In other words, absolute value ensures your number is positive, while sign tells you if the number is negative.
I know use cases for these, but explaining them would make this chapter needlessly convoluted. Just know that they exist.
Yes, I choose brevity and withholding information over “explain everything in-depth”. After years of teaching and researching how people learn most efficiently, this is one of my main take-aways. The biggest obstacle to learning is trying to do too much of it (at once).
Trigonometry
CSS also supports all the trigonometric functions. These all take an angle as input. (Which is a number with unit deg
for degrees or rad
for radians.)
sin
andasin
cos
andacos
tan
andatan
Moreover, it supports power functions.
pow(base, number)
for exponentials.exp(number)
for exponentials with Euler’s number (e
) as the base.sqrt(val)
for the square root.log(val, base)
for logarithms. The second input is optional; when left out, Euler’s number is assumed.
Below is a very convoluted example. But it’s there to show you the power of all these functions and how they can be combined.
Want to support me?
Buy one of my projects. You get something nice, I get something nice.
Donate through a popular platform using the link below.
Simply giving feedback or spreading the word is also worth a lot.