@mixin and @include

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 are defined using the @mixin at-rule, which is written @mixin <name> { ... } or @mixin name(<arguments...>) { ... }. A mixin’s name can be any Sass identifier, and it can contain any statement other than top-level statements. They can be used to encapsulate styles that can be dropped into a single style rule; they can contain style rules of their own that can be nested in other rules or included at the top level of the stylesheet; or they can just serve to modify variables.

Mixins are included into the current context using the @include at-rule, which is written @include <name> or @include <name>(<arguments...>), with the name of the mixin being included.

SCSS Syntax

@mixin reset-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin horizontal-list {
  @include reset-list;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: 2em;
    }
  }
}

nav ul {
  @include horizontal-list;
}

Sass Syntax

@mixin reset-list
  margin: 0
  padding: 0
  list-style: none


@mixin horizontal-list
  @include reset-list

  li
    display: inline-block
    margin:
      left: -2px
      right: 2em




nav ul
  @include horizontal-list

CSS Output

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}











Arguments

Mixins can also take arguments, which allows their behavior to be customized each time they’re called. The arguments are specified in the @mixin rule after the mixin’s name, as a list of variable names surrounded by parentheses. The mixin must then be included with the same number of arguments in the form of SassScript expressions. The values of these expression are available within the mixin’s body as the corresponding variables.

SCSS Syntax

@mixin rtl($property, $ltr-value, $rtl-value) {
  #{$property}: $ltr-value;

  [dir=rtl] & {
    #{$property}: $rtl-value;
  }
}

.sidebar {
  @include rtl(float, left, right);
}

Sass Syntax

@mixin rtl($property, $ltr-value, $rtl-value)
  #{$property}: $ltr-value

  [dir=rtl] &
    #{$property}: $rtl-value



.sidebar
  @include rtl(float, left, right)

CSS Output

.sidebar {
  float: left;
}
[dir=rtl] .sidebar {
  float: right;
}





Optional Arguments

Normally, every argument a mixin declares must be passed when that mixin is included. However, you can make an argument optional by defining a default value which will be used if that arguments isn’t passed. Default values use the same syntax as variable declarations: the variable name, followed by a colon and a SassScript expression. This makes it easy to define flexible mixin APIs that can be used in simple or complex ways.

SCSS Syntax

@mixin replace-text($image, $x: 50%, $y: 50%) {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;

  background: {
    image: $image;
    repeat: no-repeat;
    position: $x $y;
  }
}

.mail-icon {
  @include replace-text(url("/images/mail.svg"), 0);
}

Sass Syntax

@mixin replace-text($image, $x: 50%, $y: 50%)
  text-indent: -99999em
  overflow: hidden
  text-align: left

  background:
    image: $image
    repeat: no-repeat
    position: $x $y

.mail-icon
  @include replace-text(url("/images/mail.svg"), 0)



CSS Output

.mail-icon {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;
  background-image: url("/images/mail.svg");
  background-repeat: no-repeat;
  background-position: 0 50%;
}







Keyword Arguments

When a mixin is included, arguments can be passed by name in addition to passing them by their position in the argument list. This is especially useful for mixins with multiple optional arguments, or with boolean arguments whose meanings aren’t obvious without a name to go with them. Keyword arguments use the same syntax as variable declarations and optional arguments.

SCSS Syntax

@mixin square($size, $radius: 0) {
  width: $size;
  height: $size;

  @if $radius != 0 {
    border-radius: $radius;
  }
}

.avatar {
  @include square(100px, $radius: 4px);
}

Sass Syntax

@mixin square($size, $radius: 0)
  width: $size
  height: $size

  @if $radius != 0
    border-radius: $radius



.avatar
  @include square(100px, $radius: 4px)

CSS Output

.avatar {
  width: 100px;
  height: 100px;
  border-radius: 4px;
}







Taking Arbitrary Arguments

Sometimes it’s useful for a mixin to be able to take any number of arguments. If the last argument in a @mixin declaration ends in ..., then all extra arguments to that mixin are passed to that argument as a list. This argument is known as an argument list.

SCSS Syntax

@mixin order($height, $selectors...) {
  @for $i from 0 to length($selectors) {
    #{nth($selectors, $i + 1)} {
      position: absolute;
      height: $height;
      margin-top: $i * $height;
    }
  }
}

@include order(150px, "input.name", "input.address", "input.zip");






Sass Syntax

@mixin order($height, $selectors...)
  @for $i from 0 to length($selectors)
    #{nth($selectors, $i + 1)}
      position: absolute
      height: $height
      margin-top: $i * $height




@include order(150px, "input.name", "input.address", "input.zip")






CSS Output

input.name {
  position: absolute;
  height: 150px;
  margin-top: 0px;
}

input.address {
  position: absolute;
  height: 150px;
  margin-top: 150px;
}

input.zip {
  position: absolute;
  height: 150px;
  margin-top: 300px;
}

Taking Arbitrary Keyword Arguments

Argument lists can also be used to take arbitrary keyword arguments. The meta.keywords() function takes an argument list and returns any extra keywords that were passed to the mixin as a map from argument names (not including $) to those arguments’ values.

SCSS Syntax

@use "sass:meta";

@mixin syntax-colors($args...) {
  @debug meta.keywords($args);
  // (string: #080, comment: #800, $variable: $60b)

  @each $name, $color in meta.keywords($args) {
    pre span.stx-#{$name} {
      color: $color;
    }
  }
}

@include syntax-colors(
  $string: #080,
  $comment: #800,
  $variable: #60b,
)

Sass Syntax

@use "sass:meta"

@mixin syntax-colors($args...)
  @debug meta.keywords($args)
  // (string: #080, comment: #800, $variable: $60b)

  @each $name, $color in meta.keywords($args)
    pre span.stx-#{$name}
      color: $color




@include syntax-colors($string: #080, $comment: #800, $variable: #60b)




CSS Output

pre span.stx-string {
  color: #080;
}

pre span.stx-comment {
  color: #800;
}

pre span.stx-variable {
  color: #60b;
}







Passing Arbitrary Arguments

Just like argument lists allow mixins to take arbitrary positional or keyword arguments, the same syntax can be used to pass positional and keyword arguments to a mixin. If you pass a list followed by ... as the last argument of an include, its elements will be treated as additional positional arguments. Similarly, a map followed by ... will be treated as additional keyword arguments. You can even pass both at once!

SCSS Syntax

$form-selectors: "input.name", "input.address", "input.zip" !default;

@include order(150px, $form-selectors...);

Sass Syntax

$form-selectors: "input.name", "input.address", "input.zip" !default

@include order(150px, $form-selectors...)

Content Blocks

In addition to taking arguments, a mixin can take an entire block of styles, known as a content block. A mixin can declare that it takes a content block by including the @content at-rule in its body. The content block is passed in using curly braces like any other block in Sass, and it’s injected in place of the @content rule.

SCSS Syntax

@mixin hover {
  &:not([disabled]):hover {
    @content;
  }
}

.button {
  border: 1px solid black;
  @include hover {
    border-width: 2px;
  }
}

Sass Syntax

@mixin hover
  &:not([disabled]):hover
    @content



.button
  border: 1px solid black
  @include hover
    border-width: 2px


CSS Output

.button {
  border: 1px solid black;
}
.button:not([disabled]):hover {
  border-width: 2px;
}






Passing Arguments to Content Blocks

Compatibility:
Dart Sass
since 1.15.0
LibSass
Ruby Sass

A mixin can pass arguments to its content block the same way it would pass arguments to another mixin by writing @content(<arguments...>). The user writing the content block can accept arguments by writing @include <name> using (<arguments...>). The argument list for a content block works just like a mixin’s argument list, and the arguments passed to it by @content work just like passing arguments to a mixin.

SCSS Syntax

@mixin media($types...) {
  @each $type in $types {
    @media #{$type} {
      @content($type);
    }
  }
}

@include media(screen, print) using ($type) {
  h1 {
    font-size: 40px;
    @if $type == print {
      font-family: Calluna;
    }
  }
}

Sass Syntax

@mixin media($types...)
  @each $type in $types
    @media #{$type}
      @content($type)




@include media(screen, print) using ($type)
  h1
    font-size: 40px
    @if $type == print
      font-family: Calluna



CSS Output

@media screen {
  h1 {
    font-size: 40px;
  }
}
@media print {
  h1 {
    font-size: 40px;
    font-family: Calluna;
  }
}





Indented Mixin Syntax

The indented syntax has a special syntax for defining and using mixins, in addition to the standard @mixin and @include. Mixins are defined using the character =, and they’re included using +. Although this syntax is terser, it’s also harder to understand at a glance and users are encouraged to avoid it.

Sass Syntax

=reset-list
  margin: 0
  padding: 0
  list-style: none

=horizontal-list
  +reset-list

  li
    display: inline-block
    margin:
      left: -2px
      right: 2em

nav ul
  +horizontal-list

CSS Output

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: inline-block;
  margin-left: -2px;
  margin-right: 2em;
}