CSS Clamp(): The Responsive Combination We’ve All Been Waiting For

Bringing Together the Best of the CSS min() and CSS max() Functions

Paige Niedringhaus
Bits and Pieces

--

Photo by Heike Mintel on Unsplash

Today is such a wonderful time to write CSS

You know that moment when you’re coding something and think to yourself: “I wish this [text, image, box, insert element of your choice here] would grow or shrink depending on the viewport size… but only up to a certain point”?

If you haven’t experienced this yet, not to worry, you will. But what you won’t have to do is come up with some complex event listeners using the Web API ResizeObserver or CSS calc() functions or even CSS media queries that would swap out complete elements or components depending on the viewport size. 😓

No, nothing requiring so much effort as that anymore, for we live in an age where CSS is awesome, and it just keeps getting better by the day (and with wider and wider spread browser support too). Today, I want to share with you the CSS clamp() function — a single function, purpose-built to allow almost any element to adjust its size within certain bounds to fit the viewport.

CSS clamp() is an element-first approach to responsive styling. An approach that is more suitable to the new world of shareable independent components.

Learn more about reusing CSS components:

A Brief History of CSS Bounds

Before I dive into CSS clamp(), however, let’s look back briefly at its two main predecessors: CSS min() and CSS max(). Understanding them will help make CSS clamp() easier to wrap your head around (and when you see some of the workarounds that used to have to happen to accomplish the same thing, you’ll be so glad it exists!).

CSS min() & CSS max()

Ok, so back in the day, there were two CSS functions known as CSS min() and CSS max().

CSS min() lets you set the smallest (most negative) value from a list of comma-separated expressions as the value of a CSS property value.

Similarly, CSS max() will set the largest (most positive) value from a list of comma-separated expressions as the value of a CSS property value.

Both the min() and max() functions can be used anywhere a <length>,<frequency>, <angle>, <time>, <percentage>, <number>, or <integer> is allowed.

Here’s a small CodePen example I put together of all three options, so can can see how each function differs when compared side by side.

Simple CodePen illustrating CSS min() and CSS max() and CSS clamp() and how they differ from each other in practice.

If you resize the browser this example runs in, you’ll see the pink and green rectangles resize accordingly (just inspect their sizes with the developer console tools to see how they adjust).

Seeing this in action in a browser really helps me understand these concepts better, so I recommend you play around with the example above before proceeding to my more detailed, technical explanations.

CSS min() Example

The pink rectangle in the CodePen above is the CSS min() example. In addition to the background-color and height for this <div>, the CSS to focus on is:

width: min(50vw, 700px);

What this ends up meaning is: the width of the pink div will be up to 700px wide, however, if the div would be smaller at 50% of the viewport width (50vw = 50 view width), it will take the smaller of the two values.

So if the viewport is 1300px wide, the <div> would end up being 650px wide (which translates to 50vw), however, if the viewport is, say, 1600px wide, the <div> would only be 700px wide, because that is the smaller value between the two options available.

It sounds backwards at first, but think of the min() value as providing the maximum value a property can have.

CSS max() Example

So if CSS min() is the max value a property can have, CSS max() provides the minimum value a property can have. Clear, right? 🙃

In the CodePen, the green <div> is the CSS max() example. Once again, I kept it bare bones to make it easier to focus on how its width changes when the viewport resizes.

width: max(50vw, 700px);

With CSS max() in effect, the <div> will end up being at least 700px wide, or 50vw — whichever is greater. For example, if the viewport is 1800px wide, the <div> will be 900px wide (because 900px is greater than 700px, the other option in this CSS max() function). If, however, the viewport is only 1200px wide, the <div> will be 700px wide, because 50vw would only be 600px, and 700px is the greater of the two values.

And while CSS min() and CSS max() offered great strides in making responsive CSS designs easier, developers wanted more, we wanted to be able to define both lower and upper bounds in the same CSS function. And so, CSS clamp() was born.

CSS clamp()

CSS clamp() offers the best of CSS min() and CSS max() combined. CSS clamp() essentially clamps a value between an upper and lower bound. clamp() enables selecting a middle value within a range of values between a defined minimum and maximum. It takes three parameters: a minimum value, a preferred value, and a maximum allowed value.

If clamp() were broken down into CSS min() and CSS max() functions, this is what it would look like: clamp(MIN, VAL, MAX) resolves to max(MIN, min(VAL, MAX)). This is what developers used to have to do to make things scale in CSS. Do you want to have to think this hard about value ranges while writing CSS? I know I don’t.

Although it’s pretty self explanatory, the MIN value is the smallest (most negative) value. This is the lower bound in the range of allowed values. If the preferred value is less than this value, the MIN value will be used.

The preferred VAL is the expression whose value will be used as long as the result is between the MIN and MAX values.

The MAX value is the largest (most positive) expression value to which the value of the property will be assigned if the preferred value is greater than this upper bound.

In the CodePen example above, the CSS clamp() code shows how the light blue <div> grows and shrinks as long as its preferred value of 60vw, is within its lower bound of 400px and its upper bound of 600px. Once the computed value of 60vw strays outside of those bounds, it becomes fixed at whichever end of the scale it is favoring.

This is the code keeping it in line:

width: clamp(400px, 60vw, 600px);

I’ve also got a couple of videos below showing CSS clamp() in the wild plus the code so you can see how it works to make other elements responsive like font sizes and images.

CSS clamp() font size example

This video shows how my website’s font scales up or down to a certain point as the viewport size changes, then stops even as the viewport continues to scale.

This first example is from my own personal website, which I’m still putting the finishing touches on before going live.

As you can see in the video, as I resize the browser, the font scales up and down with the browser size, but if you watch closely, you’ll notice that at a certain point, the font stops shrinking or growing. Thanks CSS clamp()!

Here’s a sample of the actual code that makes the various font-elements on the page scale:

div { 
// other CSS...
font-size: clamp(1.1rem, 0.7153rem + 1.6368vw, 1.5rem);
}

Now before you think I figured this preferred value out on my own, I didn’t. This excellent article from Pedro Rodriguez on CSS Tricks has an awesome little calculator he made where you can plug in the MIN and MAX font-sizes and it will compute the preferred font-size value to plug in between them so they scale while staying readable throughout.

I highly recommend trying it out yourself for any responsive font-sizing you may need as well.

To break down this code though, the font-size will be set at 1.1rem, until the computed value of 0.7153rem + 1.6368vw becomes greater than that of 1.1rem. At this point, the font-size value will be calculated by the formula of 0.7153rem + 1.6368vw, until this preferred value's computed value becomes greater than that of 1.5rem. At this point, the font-size will be set at 1.5rem.

I’ll admit the formula in the place of the preferred middle value is a little confusing, but imagine it — this one little line of CSS can do all this. From a full screen desktop view to mobile and back again with just one line of CSS clamp(). How cool is that?

Want another real world example? Here’s one with both the logo image and font resizing with clamp()'s assistance.

CSS clamp() image & font size example

This video shows how the logo and font for this under construction website I built scales up or down to a certain point as the viewport size changes, then stops even as the viewport continues to scale.

This is a one-page placeholder website I built while this business gets up and running, but although it’s simple I still wanted it to be responsive and look good across different device sizes. So I reached once more for CSS clamp().

For the logo, the CSS code is simply:

.logo {    
width: clamp(350px, 75%, 800px);
}

And the font’s CSS is:

.title {   
// additional css
font-size: clamp(1.5rem, 5vw, 4rem);
}

That’s it — that’s all there is to it. No other CSS media queries, nothing, nada. It. Just. Works.

Ready to get on board with CSS clamp(), yet?

Conclusion

I am a developer who really enjoys frontend development the most. Nice UIs, smooth animations, bright colors and the ever growing list of things that make such frontends a pleasure to build.

CSS clamp() has definitely earned a spot on that list. Responsive websites are a must-have in today’s world, but making sure they look good on all devices is a big challenge, even for what looks like a relatively simple sight at first glance.

clamp() makes it easier. Need that text to get smaller for mobile but not unreadably tiny print? clamp() can handle it. Want that image to scale up when a user’s on a large desktop monitor? clamp() can handle it. Should that <div> flex within certain bounds to fill the viewport as intended in the design? clamp() can handle it. From now on, whenever I need responsive within upper and lower bounds, I’ll ask myself if CSS clamp() is right for the job.

Check back in a few weeks — I’ll be writing more about JavaScript, React, ES6, or something else related to web development.

Thanks for reading. I hope you come away with a better understanding of how the CSS function clamp() works, and that if the situation calls for it, you can add it to your own responsive frontend application. It’s amazing what’s possible now with just a few lines of code!

Build better Component Libs and Design Systems

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

Learn more:

References & Further Resources

--

--

Staff Software Engineer at Blues, previously a digital marketer. Technical writer & speaker. Co-host of Front-end Fire & LogRocket podcasts