Future of CSS: Functions and Mixins
Tags: css, webdev, future
Published: 2024-02-15 21:55:42

Today we're going to look at something that hasn't yet been incorporated into the official CSS specification but could change the way we write CSS. I am, of course, talking about [Functions and Mixins](https://github.com/w3c/csswg-drafts/issues/9350).

Here's the TL;DR, CSS Functions and Mixin add a way to capture and reuse CSS logic without the use of pre-processors. This allows `DRY` principles to be executed in CSS without the need of utility classes.

Let's dive in and see how we got here and what these changes may mean in practice.

## CSS pre-processors

Traditionally CSS lacked features such as variables, nesting, mixins, and functions. This was frustrating for Developers as it often led to CSS quickly becoming complex and cumbersome. In an attempt to make code easier and less repetitive CSS pre-processors were born. You would write CSS in the format the pre-processor understood and, at build time, you'd have some nice CSS. The most common pre-processors these days are [Sass](https://sass-lang.com/), [Less](https://lesscss.org/), and [Stylus](https://stylus-lang.com/). Any examples I give going forward will be about Sass as that's what I'm most familiar with.

![Sass logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikp0vrqrj8kvrzrcu61j.png)

Pre-processors were not without their problems though; for one, the browser can't understand them, you need a build/compile step before you can see what they're doing. For another, each pre-processor has a slightly different syntax for devs to learn and master.

Perhaps as an attempt to remedy this or perhaps just a way to improve vanilla DX (Developer eXperience) the CSS spec began to incorporate aspects of Pre-processors with `variables` and more recently `nesting`.

### Sass `@function`

> Functions allow you to define complex operations on SassScript values that you can re-use throughout your stylesheet. They make it easy to abstract out common formulas and behaviours in a readable way.

[Functions in Sass](https://sass-lang.com/documentation/at-rules/function/) allows a developer to calculate a single value. This will be calculated at build time so can not include vanilla CSS Variables.

### Sass `@mixin`

> Mixins allow you to define styles that can be re-used throughout your stylesheet. They make it easy to avoid using non-semantic classes like .float-left, and to distribute collections of styles in libraries.

[Mixins in Sass](https://sass-lang.com/documentation/at-rules/mixin/) allows a developer to `@include` a whole block of css (property and value pairs). It also allows you to pass in arguments that can modify the block. Though, again as this is calculated at build time vanilla CSS Variables aren't available.

## Examples and use cases

Let's suppose we have a design system where we have buttons that can be different colours, each button should look the same apart from the different background colour, the hover and active states are slightly darker variants of their base colour.

First let's make a function that will mix any colour with black at a set percentage.

```css
@function --darken(--base, --percent) {
  @return color-mix(in srgb, var(--base), #000 var(--percent));
}
```

Now that we have a function that can darken our base colours let's make a mixin that will make our default button style with the hover and active states, we can use nesting in the mixin to make this easier.

You'll notice the `--color` argument has a default colour which will be used if one isn't supplied.

```css
@mixin --button(--color: #174D7C) {
  background-color: var(--color);
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  font-size: 1rem;
  cursor: pointer;

  &:hover {
    background-color: --darken(var(--color), 5%);
  }

  &:active {
    background-color: --darken(var(--color), 10%);
  }
}
```

Finally let's make three buttons one using the default colour then a green and also an orange one.

```css
.primary-btn {
  @apply --button
}

.green-btn {
  @apply --button(#6F9F9C)
}

.orange-btn {
  @apply --button(#FE5F55)
}
```

![Three buttons matching the colour themes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8moka8kj5ao4zgo6s8xi.png)

And just like that we have 3 beautiful buttons with the bulk of our CSS only being written once and everything being calculated at run time. Meaning we get full reign of native CSS variables.

## Fin

Just when we think the faucet of CSS changes has been shut off something huge like this comes our way. Whilst it will take a while to be finalised into spec and then a while more roll out to browsers the possibilities are simply mind boggling.

Thanks so much for reading. If you'd like to connect with me outside of Dev here are my [twitter](https://twitter.com/Link2Twenty) and [linkedin](https://www.linkedin.com/in/andrew-bone-ba241b179/) come say hi 😊.