When laying out a page, we often run into particular situations: an element that
has to be wider than its parent but with a relative value, or fluid type that
lives between a range of values and depends on the screen width. To match in
code the result presented by the UX/UI team, we have to invent systems that let
us create these styles. That is where the CSS function calc() not only shines
but is essential, because it allows mathematical calculations using different
units. Today we are going to look at other functions also collected in the
working draft
CSS Values and Units Module Level 4
that already have broad support:
min(), max() and clamp().
Min()
min() is a CSS function that can be applied to any property that supports one
of the types <length>, <frequency>, <angle>, <time>, <percentage>,
<number> or <integer>. Given a series of comma-separated values
(parameters), it picks the smallest among them and applies it as the
property value.
.element {
width: min(500px, 70%);
}
The way to read the example above would be: “Right now, which is the smallest value? 500px, or 70% of the parent container’s width?”
If the parent container were 1000px, we would be looking for the smallest value between 500px and 700px, so the width would be 500px.
We emphasise “Right now” because the interesting part is that if the screen size or the zoom changes, the parent container’s width changes, and therefore so does the result of that 70%. If the container were now 500px, 70% would be 350px, so the value to apply would be 350px, not 500px as before.
In practice, with this formula we are guaranteeing a maximum value that cannot
be exceeded. If we use it for a <width>, we could read it as the equivalent
of <width> and <max-width> together, because we have a <width> (70%) and a
<max-width> (500px).
Ideally the values passed to the function are of different units or relative, because if they were of the same unit and absolute, such as “500px, 550px”, the property would lose its point
Max()
max() is another CSS function that can be applied to any property that
supports one of the types <length>, <frequency>, <angle>, <time>,
<percentage>, <number> or <integer>. From the comma-separated parameters
it receives, it picks the largest, which will be applied as the property
value.
.element {
width: max(40em, 98%);
}
In this case we would read the example as: “Right now, which of the two values is larger? 40em, or 98% of the parent container’s width?”
Because the conditions in which the content is being rendered can change, the beauty and power of the function lie in its re-evaluation, so it can pick the value that fits best in each situation.
Here we are guaranteeing a minimum value for that property. If we use it for
a <width>, we could read it as the equivalent of <width> and <min-width>
together, because we have a <width> (98%) and a <min-width> (40em).
For both
min()andmax(), the order of the parameters does not matter, because sometimes the first parameter will be the largest/smallest and sometimes it will be the second
Clamp()
We can think of clamp() as the function that groups the previous two. It must
receive 3 parameters, in a specific order: MIN_VALUE, IDEAL_VALUE and
MAX_VALUE.
The function is resolved with the formula: max(MIN_VALUE, min(IDEAL_VALUE,
MAX_VALUE)). In words: “Pick the larger value between the minimum (which
works as a lower bound) and the maximum that resulted from resolving min()
between the ideal value and the maximum (which works as an upper bound)”.
.element {
font-size: clamp(14px, 3em, 4rem);
/*
Assuming that 1em = 10px, 3em = 10px * 3 = 30px
and that 1rem = 16px, 4rem = 16px * 4 = 64px
We would transform it into
*/
font-size: clamp(14px, 30px, 64px);
/*
Applying the formula we would transform it again into
*/
font-size: max(14px, min(30px, 64px));
font-size: max(14px, 30px);
font-size: 30px;
}
We would be talking about a property similar to the flex shorthand, but in
practice it would be like applying (if we were setting a width) <min-width>,
<max-width> and <width>.
clamp(MIN, VAL, MAX) is resolved as max(MIN, min(VAL, MAX))
Common properties and uses
-
min(),max()andclamp()can be used together withcalc(), and they can also be nested, that is, combined:calc(min()),max(calc()),calc(max(min())), and so on. -
They allow simple math such as addition, subtraction, multiplication and division, and because they are math functions it is not necessary to nest
calc()inside them: parentheses are enough.
.element-a {
font-size: max(min(10%, ((1.25vw + 10px) * 0.5), 5vw), 1rem);
}
.element-b {
font-size: max(min(10%, calc((1.25vw + 10px) * 0.5), 5vw), 1rem);
}
- They are very useful for fluid typography and for improving the
accessibility of a project, because with
max()andclamp()we can set a minimum font size for our text that always keeps it readable.
.text {
/* Guarantee that a text value can never be smaller than 18px */
font-size: clamp(18px, (1rem + 1vw) * 1.25, 3rem);
}
Using them in Sass
When using min() and max() in Sass (SCSS), the compiler (LibSass or Ruby
Sass) throws an error for incompatible units. As the
official documentation
explains, this is because they interpret min() and max() as Sass’s own
functions, not as the CSS functions (which arrived much later). That is why, to
use these implementations, they recommend treating them as a string:
.element-c {
width: unquote("min(500px, 98%)");
}
.element-d {
font-size: unquote("max(min(10%, ((1.25vw + 10px) * 0.5), 5vw), 1rem)");
}
Another solution, very smart in its simplicity, comes from
Ana Tudor in a
CSS-Tricks article titled “When Sass and new
CSS features conflict”, which I reached through
CodePen’s reply when I asked the question on
Twitter. The
article goes deep into computation with unrelated values, special cases and
native CSS variables, but the solution is a language basic: Sass is
case-sensitive but CSS is not, so the Sass compiler would not understand
Min() as its internal function and the error would not happen. The resulting
CSS, which does not make that distinction, interprets MIN(), Min() and
min() the same way, so we could use these functions without problems.
Conclusion
It is worth noting that although clamp() is the most complex of the three, it
is also the most complete, and in practice, after a little use, you will realise
it is the one you will use the most — if not the only one.
These 3 functions let us add a bit more logic, flexibility and control to our
stylesheets, which helps us build more powerful applications and enrich them to
meet increasingly demanding results. Understanding how min(), max() and
clamp() work will give us new tools to face a layout with more resources and,
potentially, to be more creative.
Demo
