Ekaterina Vujasinović
Posted on May 19, 2020
We use relative length units to build responsive/fluid layouts. Besides being flexible, elements whose size depends on the size of another element or the viewport, also have a bad habit of sometimes growing or shrinking more than we would like them to. For example, if we define the font size with vw
unit alone, text can easily become illegible if viewport size gets too small.
Breaking a bad habit is tough - and in this case it may require some serious thinking and calculations. We usually solve these problems with media queries or different calc()
techniques to achieve more fluid effect. It's especially true when it comes to the elements that don't have width
property (and consequently max-width
and min-width
), like the above-mentioned font size.
Comparison functions can help us build responsive designs with less time and fewer lines of code. Functions clamp()
, min()
and max()
(specified in CSS Values and Units Module Level 4) set upper and/or lower value limits, compute and compare values of the arguments passed to the function, and apply the calculated value to the property.
clamp()
, min()
and max()
can take values or math expressions as arguments (or basically anything that resolves to a value). They can be used, let me quote MDN here: anywhere a <length>
, <frequency>
, <angle>
, <time>
,<percentage>
, <number>
, or <integer>
is allowed. That’s a lot of possible use cases to consider, and in this post I explored the most obvious ones.
clamp()
Function clamp()
takes three parameters: a minimum value, a central, preferred value, and a maximum value. The resolved value will always remain between the minimum and maximum.
clamp()
calculates property value based on the central value. If the calculated value falls between the minimum and maximum, the central value will be applied to the element. If the calculated value falls below minimum or exceeds maximum, minimum or maximum will be applied respectively. There is no need for calc()
function when passing math expressions in the comparison function.
The syntax is simple and logical:
/* css */
.element {
width: clamp(100px, 50vw, 600px);
/* width: clamp(min, preferred, max); */
}
Depending on the viewport size, the upper CSS ruleset will apply the following widths to the element:
Viewport | Applied width clamp() |
---|---|
200px - 1200px | 50vw |
< 200px | 100px |
> 1200px | 600px |
Try it for yourself in the clamp()
demo below:
Check another demo to see how both the paragraph text and the heading are being smoothly resized between the value limits. No jumps as with media queries. The ratio between the font size of the headline and body text grows as the viewport gets bigger but nothing will ever get too big or too small.
This is a simple example and is far from perfect - vertical rhythm, modular scale, line length, and bazillion other typography related things - it all could be implemented better. But if I ever decide to improve it, I will probably use comparison functions for much of the above.
max() and min()
Function max()
calculates and applies the largest value from the provided range of values. Likewise, function min()
calculates and applies the smallest value from the range. They can take one or more parameters.
Check the Codepen demo below to see both functions in action:
Yes, both min()
and max()
can be replaced with max-width
or min-width
if the element has width property and only two parameters are passed into the function. It sounds a bit counterintuitive, but max()
actually sets the lower size limit and min()
the upper size limit.
/* css */
/* min() */
.element {
width: min(50vw, 500px);
}
/* gives the same result as: */
.element {
width: 50vw;
max-width: 500px;
}
/* max() */
.element {
width: max(50vw, 500px);
}
/* gives the same result as: */
.element {
width: 50vw;
min-width: 500px;
}
The upper CSS code applies following width values to the element, depending on the viewport size:
Viewport | Applied width max() | Applied width min() |
---|---|---|
> 1000px | 50vw | 500px |
< 1000px | 500px | 50vw |
You can pass multiple parameters into both max()
and min()
:
/* css */
h1 {
font-size: min(3rem, 3em, 4vw);/* the smallest value will be applied */
}
max()
and min()
with multiple parameters are potentially capable of doing some serious responsive stuff with a single line of code. However, I find them a bit incomprehensive - it's hard to set the right arguments and it's even harder to check which value gets applied 🤯. Maybe there are some best practices I'm not aware of.
In the following demo the rectangle changes its width and color as the width property takes three different values:
Comparison functions can be nested within other comparison functions. For example, function clamp()
can be alternatively written as max(minimum, min(preferred, maximum))
.
Conclusion
Comparison functions are new to me and I still haven't find time to fully explore them. They have only recently entered some major browsers but already have decent browser support.
I can imagine comparison functions being used in web typography. It's not like it will absolve us from using media queries or calc()
, but in many cases they can make our job a lot easier.
Potential use cases of comparison functions probably stretch far beyond responsive width and font-size. I was thinking about how to use them with colors (still thinking 🥴). Maybe you have some interesting ideas? Share your thoughts in comments.
Posted on May 19, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024