Sass and clamp
Tags: css, sass, clamp, fluid
Published: 2020-05-13 18:57:48

---
title: Sass and clamp
published: true
date: 2020-05-13 14:34:07 UTC
tags: css,sass,clamp,fluid
canonical_url: https://adactio.com/journal/16887
---

CSS got some pretty nifty features recently. There’s the `min()` and `max()` functions. If you use them for, say, `width` you can use one rule where previously you would’ve needed to use two (a `width` declaration followed by either `min-width` or `max-width`). But they can also be applied to `font-size`! That’s very nifty—we’ve never had `min-font-size` or `max-font-size` properties.

There’s also the `clamp()` function. That allows you to set a minimum size, a default size, and a maximum size. Again, it can be used for lengths, like `width`, or for `font-size`.

Over on [thesession.org](https://thesession.org), I’ve had some media queries in place for a while now that would increase the `font-size` for larger screens. It’s nothing crucial, just a nice-to-have so that on wide screens, the font is bumped up accordingly. I realised I could replace all those media queries with one `clamp()` statement, thanks to the `vw` (viewport width) unit:

```
font-size: clamp(1rem, 1.333vw, 1.5rem);

```

By default, the font-size is `1.333vw` (1.333% of the viewport width), but it will never get smaller than `1rem` and it will never get larger than `1.5rem`.

That works, but there’s a bit of an issue with using raw `vw` units like that. If someone is on a wide screen and they try to adjust the font size, nothing will happen. The viewport width doesn’t change when you bump the font size up or down.

The solution is to mix in some kind of unit that _does_ respond to the font size being bumped up or down (like, say, the `rem` unit). Handily, `clamp()` allows you to combine units, just like `calc()`. So I can do this:

```
font-size: clamp(1rem, 0.5rem + 0.666vw, 1.5rem);

```

The result is much the same as my previous rule, but now—thanks to the presence of that `0.5rem` value—the font size responds to being adjusted by the user.

You _could_ use a full `1rem` in that default value:

```
font-size: clamp(1rem, 1rem + 0.333vw, 1.5rem);

```

…but if you do that, the minimum size (`1rem`) will never be reached—the default value will _always_ be larger. So in effect it’s no different than saying:

```
font-size: min(1.rem + 0.333vw, 1.5rem);

```

[I mentioned this to Chris just the other day](https://css-tricks.com/min-max-and-clamp-are-css-magic/#comment-1756630).

Anyway, I got the result I wanted. I wanted the font size to stay at the browser default size (usually 16 pixels) until the screen was larger than around 1200 pixels. From there, the font size gets gradually bigger, until it hits one and a half times the browser default (which would be 24 pixels if the default size started at 16). I decided to apply it to the `:root` element (which is `html`) using percentages:

```
:root {
  font-size: clamp(100%, 50% + 0.666vw, 150%);
}

```

(My thinking goes like this: if we take a screen width of 1200 pixels, then `1vw` would be 12 pixels: 1200 divided by 100. So for a font size of 16 pixels, that would be `1.333vw`. But because I’m combining it with half of the default font size—50% of 16 pixels = 8 pixels—I need to cut the `vw` value in half as well: 50% of `1.333vw` = `0.666vw`.)

So I’ve got the CSS rule I want. I dropped it in to the top of my file and…

I got an error.

There was nothing wrong with my CSS. The problem was that I was dropping it into a Sass file (`.scss`).

Perhaps I am showing my age. Do people even use Sass any more? I hear that post-processors usurped Sass’s dominance (although no-one’s ever been able to explain to me why they’re different to pre-processers like Sass; they both process something you’ve written into something else). Or maybe everyone’s just writing their CSS in JS now. I hear that’s a thing.

[The Session](https://thesession.org/) is a looooong-term project so I’m very hesitant to use any technology that won’t stand the test of time. When I added Sass into the mix, [back in—I think—2012 or so](https://adactio.com/journal/5918/), I wasn’t sure whether it was the right thing to do, from a long-term perspective. But it did offer some useful functionality so I went ahead and used it.

Now, eight years later, it was having a hard time dealing with the new `clamp()` function. Specifically, it didn’t like the values being calculated through the addition of multiple units. I think it was clashing with Sass’s in-built ability to add units together.

I started to ask myself whether I should still be using Sass. I looked at which features I was using…

**Variables**. Well, now we’ve got CSS custom properties, which are even more powerful than Sass variables because they can be updated in real time. Sass variables are like `const`. CSS custom properties are like `let`.

**Mixins**. These can be very useful, but now there’s a lot that you can do just in CSS with `calc()`. The built-in `darken()` and `lighten()` mixins are handy though when it comes to colours.

**Nesting**. I’ve never been a fan. I know it can make the source files look tidier but I find it can sometimes obfuscate what you’re final selectors are going to look like. So this wasn’t something I was using much any way.

**Multiple files**. Ah! This is the thing I would miss most. Having separate `.scss` files for separate interface elements is very handy!

But globbing a bunch of separate `.scss` files into one `.css` file isn’t really a Sass task. That’s what build tools are for. In fact, that’s what I was already doing with my JavaScript files; I write them as individual `.js` files that then get concatenated into one `.js` file using Grunt.

(Yes, this project uses Grunt. I told you I was showing my age. But, you know what? It works. Though seeing as I’m mostly using it for concatenation, I could probably replace it with a makefile. If I’m going to use old technology, I might as well go all the way.)

I swapped out Sass variables for CSS custom properties, mixins for `calc()`, and removed what little nesting I was doing. Then I stripped the Sass parts out of my Grunt file and replaced them with some concatenation and minification tasks. All of this makes no difference to the actual website, but it means I’ve got one less dependency …and I can use `clamp()`!

Remember a little while back when I was [making a dark mode for my site](https://adactio.com/journal/15941)? I made this observation:

> Let’s just take a moment here to pause and reflect on the fact that we can now use CSS to create all sorts of effects that previously required a graphic design tool like Photoshop.

It feels like something similar has happened with tools like Sass. Sass was the hare. CSS is the tortoise. Sass blazed the trail, but now native CSS can achieve much the same result.

It’s like when we used to need something like jQuery to do DOM Scripting succinctly using CSS selectors. Then we got things like `querySelector()` in JavaScript so we no longer needed the trailblazer.

I’ve said it before and I’ll say it again, the goal of any good library should be to get so successful as to make itself redundant. That is, the ideas and functionality provided by the tool are so useful and widely adopted that the native technologies—HTML, CSS, and JavaScript—take their cue from those tools.

You could argue that this is what happened with Flash. It certainly happened with jQuery and Sass. I’m pretty sure we’ll see the same cycle play out with [frameworks like React](https://gomakethings.com/how-to-create-a-state-based-ui-component-with-vanilla-js/).