Creating a clamp() fallback function in Sass/SCSS

Rather than using calc() and media queries to create fluid elements within min/max allowable values, on a new project I wanted to determine whether the new CSS functions of min(), max() and clamp() could be used instead.

Browser support is pretty good across all modern browsers, though clamp() isn’t available in all but the very latest version of Safari (at time of writing). With that in mind, I wanted to ensure suitable fallbacks were in place. The result was the following…

font-size:24px; font-size:min(max(12px, 3vw), 24px); font-size:clamp(12px,3vw,24px);

I didn’t want to discount older browsers like IE11 and Opera Mini completely as they don’t support any of these new functions at all, hence the standard font-size fallback.

It might be overkill to also provide a fallback for browsers that do support min() and max() but not clamp() through combining the min() and max() functions together, but as this is my first foray into using these on a live project I decided an element of caution was ok.

Min what? Max where? Clamp who?

If you’re unaware of the min(), max() and clamp() functions, they work like this…

padding-top:min(10vw, 100px); padding-top:max(10vw, 100px);

Essentially the min() function determines which of the two values is the largest and uses that. In the example above we’re specifying 100px as the minimum value padding-top can be, so if 10vw becomes less than this the browser will set the value as 100px, otherwise it will be whatever 10vw could be, which on a 2000px viewport would be 200px.

max() works the opposite way, selecting the smallest amount below the maximum allowable value we set.

padding-top:clamp(100px, 10vw, 200px);

For clamp() we include three parameters (min, value, max). The value is the one the browser will look to first, this is what we want padding-top to be in this case, however if that value becomes smaller than the first parameter, or larger than the last parameter then the browser will use the appropriate min or max value.

Using Sass/Scss

One challenge came when attempting to use the min() and max() functions with Sass. As Sass already had a min() and max() functions the use of the standard CSS min() function would cause an error. While different solutions were offered through the web, ultimately, the following was the solution I needed…

padding-top:#{"min(100px,10vw)"};
/* or */
padding-top:#{"min(max(100px, 10vw), 200px)"}

Not being able to use the function as standard was a bit of a pain really, but it did help lead me towards to creating a mixin to simplify doing this and more, at least when it came to using clamp().

The Mixin

@mixin clamp($property, $min-size, $scaler, $max-size, $min-size-left:false, $scaler-left:false, $max-size-left:false){
  @if $min-size-left == false {
    #{$property}:$max-size; 
    #{$property}:#{"min(max(#{$min-size}, #{$scaler}), #{$max-size})"}; 
    #{$property}:clamp($min-size, $scaler, $max-size);
  } @else if $min-size-left == 0 or $min-size-left == auto{
    #{$property}:$max-size $min-size-left; 
    #{$property}:#{"min(max(#{$min-size}, #{$scaler}), #{$max-size})"} $min-size-left;
    #{$property}:clamp($min-size, $scaler, $max-size) $min-size-left;
  } @else {
    #{$property}:$max-size $min-size-left; 
    #{$property}:#{"min(max(#{$min-size}, #{$scaler}), #{$max-size})"} #{"min(max(#{$min-size-left}, #{$scaler-left}), #{$max-size-left})"}; 
    #{$property}:clamp($min-size-left, $scaler-left, $max-size-left);
  }
}

This mixin function allows the following use cases…

/* Simple one value */
@include clamp(‘font-size’,12px,3vw,24px);

/* Which outputs... */
font-size:24px; font-size:min(max(12px, 3vw), 24px); font-size:clamp(12px,3vw,24px);


/* Margin-top simple one value */
@include clamp(‘margin-top’,100px,10vw,200px);

/* Which outputs... */
margin-top:100px; margin-top:min(max(100px, 10vw), 200px); margin-top:clamp(100px,10vw,200px);


/* Margin shorthand [value] [0/auto] */
@include clamp(‘margin’,100px,10vw,200px,0);

/* Which outputs... */
margin:200px 0; margin:min(max(100px, 10vw), 200px) 0; margin:clamp(100px,10vw,200px) 0;
/* * Unfortunately margin:[0/auto] [value] isn’t supported.*/


/* Margin shorthand with values for top/bottom & left/right */
@include clamp(‘margin’,100px,10vw,200px,50px,5wv,100px);

/* Which outputs... */
margin:200px 100px; margin:min(max(100px, 10vw), 200px) min(max(50px, 5vw), 100px); margin:clamp(100px,10vw,200px) clamp(50px,5vw,100px);

In addition to providing the fallbacks shown in the first code example of this article, the mixin also allows you to specify the property you want to use as well as handle shorthand values where you’re passing one or two values.

In future I may drop the min()/max() reference in favour of clamp() only, but for now it’s a useful little function to quickly author fluid measurements with appropriate fallbacks.


We'd love to hear from you!

If you think Bronco has the skills to take your business forward then what are you waiting for?

Get in Touch Today!

Discussion

Add a Comment