Dynamic Sizing with CSS max()

Hero image for Dynamic Sizing with CSS max(). Image by Nagy Arnold.
Hero image for 'Dynamic Sizing with CSS max().' Image by Nagy Arnold.

It wasn't that long ago that CSS functions like max() (or min(), or clamp()) were entirely unthinkable: these open up access to dynamic values and functionality that could only be achieved historically through the use of JavaScript. Now, they play a really important role in our ability to develop fluid, responsive layouts, elegantly adapting across different devices.


Unpacking max()

Much like it's sibling min(), max() is very straightforward at it's core; it accepts and evaluates a set of values, and returns the largest. This allows us as developers and designers to expand elements to fill available space, whilst also maintaining a limit for usability and aesthetics.

Here's a simple example to get us started:

.container {  height: max(50vh, 30rem);}

Here, we define the height of an element: .container. Using max(), the overall height of .container will be set to either 50% of the viewport height (50vh) or 30rem, whichever of the two is the greater. I should mention here that there's no limit to the number of different values you can place within max(), this could easily be a combination of viewport, percentage, fixed, and fluid units all together in a single statement. The browser would still select whichever of the values is largest at that time.


Practical Applications

Responsive or Adaptive Typography

In a very similar vein to that which I described for min(), one of the most interesting and powerful uses for max() is in adaptive (or responsive) typography.

Here's a quick example where the font size of an h1 heading will increase as the viewport does but will never be smaller than 2rem:

h1 {  font-size: max(2rem, 5vw);}

Using max() in this way means that we can ensure that our text remains legible across screen sizes without becoming disproportionately small (or large).

Responsive Spacing and Layouts

Beyond typography, max() is of course invaluable when it comes to implementing responsive layouts and spacing when elements need to expand based on content or viewport size, but still have a logical maximum.

Here's another example:

.section {  padding: max(1rem, 3vw);}

As is often the case in my articles, this is a simple (but hopefully illustrative) example; the padding around .section will grow as the viewport does potentially offering more breathing room around the responsive heading we described above. However, it will also be restricted (or capped) at 1rem, preventing overly spacious of awkward layouts on larger screens.


Browser Support and Considerations

As will all sound very familiar if you've read this same section on my article about min(), browser support for max() is very good, mirroring min() exactly. However, if you still need to support more legacy browser such as Internet Explorer, then you're going to have to give a little more thought to how you structure your code.

There are two general strategies that you could consider:

Media Queries

I would argue that the power of these types of dynamic value functions comes from the fact that they do away with the need for lots of media queries. Nevertheless, in browser environments where max() isn't available, media queries will achieve similar results.

Revisiting our example from up towards the top of the article, you could achieve the same with a little more code like this (and have it work on Internet Explorer):

.container {  height: 30rem;}@media (min-height: 30rem) {  .container {    height: 50vh;  }}

The min* and max* properties

However, if we're only looking for a max between two values (rather than a wider array) and using certain dimensional properties (width, height, etc), then the same can be achieved using a combination of dimension properties (in this case: height), and the min* or max* properties. Like this:

.container {  height: 50vh;  min-height: 30rem;}

This achieves sort of the same thing in that .container will have a height of 50vh, but will also always be a minimum of 30rem high.

Admittedly, the comparison between two values like this is a fairly rudimentary use for max() anyway, so this solution isn't going to cover more indepth use cases. However, there is an argument that if what you need to achieve is this simple anyway, there's really no need to use max() (or min()) at all...


Categories:

  1. CSS
  2. Front‑End Development
  3. Responsive Development