Clamping a Number

In computer science, we use the word clamp as a way to restrict a number between two other numbers. When clamped, a number will either keep its own value if living in the range imposed by the two other values, take the lower value if initially lower than it, or the higher one if initially higher than it.

As a quick example before going any further:

$clamp: clamp(42, $min: 0, $max: 1337);    // 42
$clamp: clamp(42, $min: 1337, $max: 9000); // 1337
$clamp: clamp(42, $min: 0, $max: 1);       // 1

Coming back to CSS. There are a few ways where you might need a number to be restricted between two others. Take the opacity property for instance: it must be a float (between 0 and 1). This is typically the kind of value you would want to clamp to make sure it's neither negative nor higher than 1.

Implementing a clamp function in Sass can be done in two ways, both strictly equivalent yet one is much more elegant than the other. Let's start with the not so great one.

The dirty one

This version relies on nested if function calls. Basically we say: if $number is lower than $min, then keep $min, else if $number is higher than $max, then keep $max, else keep $number.

/// Clamp `$number` between `$min` and `$max`
/// @param {Number} $number - Number to clamp
/// @param {Number} $min - Minimum value
/// @param {Number} $max - Maximum value
/// @return {Number}
@function clamp($number, $min, $max) {
  @return if($number < $min, $min, if($number > $max, $max, $number));
}

If you are not very confident with nested if calls, think of the previous statement as:

@if $number < $min {
  @return $min;
} @else if $number > $max {
  @return $max;
}

@return $number;

The clean one

This version is much more elegant since it makes a good use of both min and max functions from Sass.

/// Clamp `$number` between `$min` and `$max`
/// @param {Number} $number - Number to clamp
/// @param {Number} $min - Minimum value
/// @param {Number} $max - Maximum value
/// @return {Number}
@function clamp($number, $min, $max) {
  @return min(max($number, $min), $max);
}

Literally means keep the minimum between $max and the maximum between $number and $min.

Example

Now, let's create a little opacity mixin just for the sake of demonstration:

/// Opacity mixin
/// @param {Float} $value - Opacity value
/// @output `opacity`
@mixin opacity($value) {
  $clamped-value: clamp($value, 0, 1);

  @if $value != $clamped-value {
    @warn "Mixin `opacity` needs a float; #{$value} given, clamped to #{$clamped-value}.";
  }

  opacity: $clamped-value;
}

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag