this is just about showing off a clamp function in scss that doesn’t break everything

(it might still break everything) (not my fault though)a website post about websites5 min read

Every sin­gle clamp func­tion for SCSS re­quires you ei­ther use a di­vi­sion func­tion that’s about to get nuked, or the re­place­ment di­vi­sion func­tion that not only re­quires an ex­tra @use, but seems to break at so much as a small breeze.

I might be as dumb as a bag of rocks, right, but I also know how SCSS han­dles calc() in such a way where it still spits out the usual clamp([#]rem, [#]rem + [#]cqi, [#]rem) I’d want, so I threw shit to­gether un­til the com­piler I use stopped yelling at me over it:

@function clmp($min, $max, $width-min: 20rem, $width-max: 40rem) {
    $slope: calc(($max - $min) / ($width-max - $width-min));
    $slopeunit: calc(100cqi * $slope);
    $baserem: calc($max - $width-max * $slope);
    @return clamp($min, $baserem + $slopeunit, $max);

Edit the $width-min and $width-max to a rem unit as you need, then call it in a cus­tom prop­erty or SCSS vari­able or what­ever like

--cool-text: #{clmp(1rem,1.125rem)};
$cool-text: clmp(1rem,1.125rem);

And it’ll work. Is it the most ef­fi­cient way to do it? I have no idea, all I know is that set­ting it up like this is why I can do re­spon­sive text that does­n’t im­plode.

Still gotta work in pix­els? Link to foot­note 1 Alright, here you go:

@function rpx($px) {
    @return calc(($px / 16px) * 1rem);

@function clmp($min, $max, $width-min: 400px, $width-max: 640px) {
    $min: rpx($min);
    $max: rpx($max);
    $width-min: rpx($width-min);
    $width-max: rpx($width-max);
    $slope: calc(($max - $min) / ($width-max - $width-min));
    $slopeunit: calc(100cqi * $slope);
    $baserem: calc($max - $width-max * $slope);
    @return clamp($min, $baserem + $slopeunit, $max);

And same as be­fore:

--cool-text: #{clmp(16px,18px)};
$cool-text: clmp(16px,18px);

This also works with the fancy new cqi unit, but con­sid­er­ing that con­ver­sion is lit­er­ally just as sim­ple as chang­ing the 100vw in your func­tion to 100cqi, that’s not par­tic­u­larly im­pres­sive. To that end, if you’ve got weird con­tain­ers, you can set cus­tom break­points through the last two vari­ables, like so:

$text-footer: clmp(0.7rem, 0.7875rem, 9rem, 16rem);

It’s prob­a­bly triv­ial to do this au­to­mat­i­cally, but the half-con­scious ver­sion of me who al­ways codes at 1am finds it kind of re­lax­ing to mea­sure it out man­u­ally, so hey.

  1. I can’t blame you if you’re old enough to where that would ob­vi­ously be how you’d think about the web, but to me it just does­n’t work well, know­ing what I know. For all the ways rem sounds ab­stract, it’s pretty un­de­ni­ably that it’s re­lated to some­thing, even if that some­thing is a generic font size; a pixel, in a world where high DPI mon­i­tors ex­ist, usu­ally is­n’t even a pixel. By that point, you might as well be us­ing inches as your unit mea­sure­ment. Return to ar­ti­cle via foot­note 1 by nomiti ityool 2024
CC BY-SA 4.0 unless marked otherwise
made with Eleventy v2.0.1

rss feed lives here
if you use this for AI i hope my dogshit sentence structure poisons it