A Bulletproof Function to Validate Length Values in Sass

Once you start getting comfortable with Sass, playing with some functions and writing your own mixins, soon enough you will want to validate developer input. This means adding some extra checks to your functions and mixins to make sure the given arguments are correct in terms of how they are going to be used within the function or mixin.

After having seen a dozen different functions supposedly aimed at validating a length, I thought I would give it a try and write something on it. So here we are.

Lengths refer to distance measurements […] A length is a dimension. However, for zero lengths the unit identifier is optional (i.e. can be syntactically represented as the ‘0’). A dimension is a number immediately followed by a unit identifier.

If we sum up what we just read, a length is a number followed by a unit, unless it’s zero. It’s a bit simplistic but we’ll start with that.

Setting Up the Function

If a function returns a Boolean, it is usually good practice to name the function with a leading is-. By the very nature of the question is [this] [that]?, we imply that the answer is either yes (true) or no (false).

In our case, we want to make sure the given value is a length, so I suggest is-length, in all its simplicity.

We return a Boolean, so there is no need to pollute the function’s core with unnecessary @if, @else if and @else directives.

We quote strings (using double quotes) because it’s more elegant and because an unquoted string is strictly equal to the same quoted string anyway.

Okay, that’s a good start. Unfortunately, most Sass frameworks that do unit validation will stop there. We cannot stop after such a good start! Also, we failed to implement correctly the CSS specification that if the value is zero, the unit is optional. Our function will return false if $value is 0 because it is unitless. Let’s fix it!

The or (||) operator is implemented like this in most languages: Keep parsing the condition until a token evaluates to true. That means if $value is 0, the function stops parsing and directly returns true, otherwise it keeps going.

Note that we could have written our condition like this as well (where parentheses are included for readability):

Our first implementation reads as if $value is 0 or $value is a number with a unit. While this implementation reads as if $value is a number and either has a unit or is 0. You can pick the one you feel the most comfortable with.

Allowing Common Values

You are probably not without knowing that there are a couple of values that can apply to all CSS properties: initial and inherit. We can also add auto to the list because most length-based properties do accept auto as a valid value. So we have three values that we want to allow, four if we count 0 that we already added previously. Let’s start with the ugly way:

The thing is, our is-length value can now return an integer. For instance, if $value is auto, then the function returns 2, because auto is the second item in our list of allowed values. While it shouldn’t be a big deal if you use @if is-length($value), there might be cases where you want to have a Boolean at all times.

In order to make sure the function returns a bool type, you can use the not-not trick (seen in the same article as above) to cast the value as a Boolean. While this is not really elegant, it works fine:

Both clear and eloquent, but needs an extra function. I’ll let you decide which is best for your needs.

Note: remember that auto is an invalid value for padding. Quite an edge case, but you should keep that in mind.

Allowing calc()

Our function is starting to get somewhere, isn’t it? However, we still need to allow calc(), which is often forgotten or omitted from length checkers. The thing with checking for calc() is that it requires Sass 3.3, because we need the str-slice method.

The idea is quite simple. We slice the first four characters from the value. If the result is “calc”, then it (likely) means the value is a calc() function, which is valid:

If you try it, you’ll see it works pretty well. I should note that we might have a problem if we try to use intrinsic sizing. In case you are not familiar with that concept, intrinsic sizing involves new valid values for both width and height properties in order to give more control to developers over the size of their elements.

The thing is, we cannot update our function to include intrinsic values since they are invalid for most properties using lengths (padding, margin, background-size, and so on). What we could do, however, is make another function using the one we already built. What about is-size?

Now we can safely use intrinsic sizing values with our brand new is-size function without fearing a falsy return! Pretty neat, right?

Final Thoughts

As I’ve shown in this article, to build a bulletproof function to validate lengths, you have to make sure you cover the most frequent edge cases (calc(), intrinsic sizing, etc).

We could still improve the function by filtering angles (deg, rad, grad, turn) and durations (s, ms) because they are currently considered as lengths by our function since they are basically a number with a unit. But since lengths, angles, and durations are used in very different contexts, there’s very little chance that the function will get passed an angle when it’s expecting a length.

Covering edge cases is nice, but covering everything including the most unlikely scenario is sometimes excessive.