Readable clamp() with PostCSS Utopia

By Trys Mudford

Fast-following from the SCSS plugin, Utopia now has a PostCSS plugin. Thanks to the abstracted utopia-core calculations, creating library-specific generators is a breeze.

So when Stefan asked the question, it seemed rude not to create a PostCSS plugin.

Installation

  1. Install the package through npm
npm install postcss-utopia
  1. Add the plugin to your postcss.config.js file:
module.exports = {
  plugins: {
    'postcss-utopia': {},
  },
}
  1. (Optional tip) You can supply global minWidth and maxWidth viewport sizes in the configuration object and skip passing them to every method in your CSS:
module.exports = {
  plugins: {
    'postcss-utopia': {
      minWidth: 320,
      maxWidth: 1080
    },
  },
}

utopia.clamp()

The most exciting method is utopia.clamp(); a shorthand way to write readable clamp functions:

.my-class {
  margin-block-end: utopia.clamp(16, 24);

  /* Generates */
  margin-block-end: clamp(1rem, 0.7895rem + 1.0526vi, 1.5rem);

  /* If you've not set minWidth & maxWidth in your config, add them here */
  margin-block-end: utopia.clamp(16, 24, 320, 1080);
}

This function generates a fluid clamp that scales from 1rem (16px) to 1.5rem (24px) between the viewports of 320px and 1080px, clamping at either end.

@utopia typeScale()

This generates a complete Utopian type scale using CSS custom properties. Any config that's valid in utopia-core is also valid here, so relativeTo: 'container', usePx: true and prefix: 'custom-name' are all usable.

:root {
  @utopia typeScale({
    minWidth: 320,          /* Defaults to plugin minWidth */
    maxWidth: 1240,         /* Defaults to plugin maxWidth */
    minFontSize: 16,
    maxFontSize: 18,
    minTypeScale: 1.2,
    maxTypeScale: 1.25,
    positiveSteps: 5,
    negativeSteps: 2,
    relativeTo: 'viewport', /* Optional */
    prefix: 'step'          /* Optional */
  });

  /* Generates
  --step--2: clamp(...);
  --step--1: clamp(...); etc.
  */
}

@utopia spaceScale()

Like typeScale above, spaceScale accepts utopia-core config, but generates three sets of custom properties:

  • Space units
  • One-up pairs
  • Custom sizes

These all map to the sizes generated on utopia.fyi:

:root {
  @utopia spaceScale({
    minWidth: 320,             /* Defaults to plugin minWidth */
    maxWidth: 1240,            /* Defaults to plugin maxWidth */
    minSize: 16,
    maxSize: 18,
    positiveSteps: [1.5, 2, 3],
    negativeSteps: [0.75, 0.5],
    customSizes: ['s-l'],
    relativeTo: 'viewport',    /* Optional */
    prefix: 'space',           /* Optional */
    usePx: false,              /* Optional */
  });

  /* Generates
  --space-2xs: clamp(...);
  --space-xs: clamp(...); etc.

  --space-2xs-xs: clamp(...); etc.

  --space-s-l: clamp(...); etc.
  */
}

@utopia clamps()

There's also method to generate multiple clamp custom properties in one go:

:root {
  @utopia clamps({
    minWidth: 320,         /* Defaults to plugin minWidth */
    maxWidth: 1240,        /* Defaults to plugin minWidth */
    pairs: [
      [16, 40]
    ],
    usePx: false,          /* Optional */
    prefix: 'space',       /* Optional */
    relativeTo: 'viewport' /* Optional */
  });

  /* Generates
  --space-16-40: clamp(...);
  */
}

Get your config

Finally, to save manually typing out your config (because who has time for that) you can grab the matching PostCSS configuration object from the type, space and clamp calculators.


First published on 6 February 2024