Jul 09, 2021

Mixins

Oftentimes, we need to apply the same groups of styles in numerous instances throughout a site. Mixins allow us to define a group of rules and insert them into selectors. We can even pass them parameters to adjust the output as needed in different contexts. Mixins are defined using the @mixin keyword, and invoked using the @include keyword.

@mixin link {
text-decoration: none;
color: $c-link;
}

a {
@include link;
}

Adding Parameters

Mixin parameters are just locally scoped variables. You can set a default for a parameter to make it optional when using the mixin, or leave it undefined to require it.

@mixin link($color: $c-link) {
text-decoration: none;
color: $color;
}

a {
@include link($color: $c-spot-alt);
}

Mixins can have as many parameters as you want. If, when invoking the mixin, you’re passing parameters in the order they appear, you can skip the definition, like so:

@mixin link($color: $c-link, $font: $display) {
color: $color;
font-family: $font;
text-decoration: none;
}

a {
@include link($c-spot-alt, $sans);
}

Nesting

Nesting in mixins behaves exactly like in selectors. Modifiers, nesting, and qualification are all functional.

@mixin link($color-base: $c-link, $color-active: $c-link-active) {
color: $color-base;
text-decoration: none;

&:hover,
&:focus
{
color: $color-active;
}
}

@content Directive

You can even write mixins that act as selectors themselves by passing their contents through with the @content directive. Such mixins are useful for shorthanding selectors, scope modifications, and composition:

@mixin on-focus {
&:hover,
&:focus
{
@content;
}
}

a {
@include on-focus {
outline: none;
}
}

Composition

Composing mixins is a powerful way to reduce repetition and increase the modularity of styles. It gives us all the same benefits of composing variables, and more.

Here’s an extremely common use case that builds upon what we’ve seen so far in this entry, and is a staple at Upstatement:

@mixin on-focus {
&:hover,
&:focus
{
@content;
}
}

@mixin focus-reset {
@include on-focus {
outline: none;
}
}

@mixin link($color-base: $c-link, $color-active: $c-link-active) {
@include focus-reset;
color: $color-base;
text-decoration: none;

@include on-focus {
color: $color-active;
}
}

a {
@include link;
}

Each setup mixin is useful in its own right, and the final invocation of the link mixin is simple, clean, and highly legible.