Sass @mixin and @include

Beginner
12 min read
Updated: Nov 2026
5 examples
Compiled CSS

Definition and Usage

Mixins let you define styles once and reuse them throughout your stylesheet. Write @mixin name { … } or @mixin name($args…) { … }, then drop them into context with @include name or @include name($args…).

They help you avoid non-semantic classes like .float-left and distribute style collections in libraries. Prefer mixins when you need to emit CSS; use @function when you only need to compute a value.

Official pattern.

Per the Sass docs: compose mixins (include one inside another), pass arguments for customization, and use @content when callers should inject their own style block.

Hyphens = underscores.

Like other Sass identifiers, reset-list and reset_list refer to the same mixin.

Compile-time only.

Mixin names never appear in CSS — only the styles they generate. Browsers never see @mixin or @include.

Syntax

SCSS
@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;
}

Pattern: define with @mixin → compose if needed → @include into a selector (or at the top level).

Args & @content

Core mixin shapes:

FormMeaning
@mixin name { … }Reusable style bundle (no args)
@mixin rtl($prop, $ltr, $rtl)Required positional arguments
$x: 50%Optional argument with a default
@include square(100px, $radius: 4px)Keyword argument at the call site
$selectors...Argument list — any number of extras
@content;Inject the caller’s style block

SCSS Examples

Each example defines and includes mixins at compile time. Open View Compiled CSS for verified output.

Example 1 — Basic Mixin

Compose mixins and include them into a selector.

SCSS
@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;
}

How It Works

  1. reset-list holds shared list resets.
  2. horizontal-list includes that mixin, then styles li.
  3. @include expands everything under nav ul.
  4. No mixin names appear in the finished CSS.

Example 2 — Arguments

Customize properties with positional arguments and interpolation.

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

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

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

How It Works

  1. #{$property} builds the property name.
  2. LTR value is set on the current selector.
  3. [dir=rtl] & places the RTL rule outside .sidebar.
  4. Reuse the mixin for margin, padding, float, and more.

Example 3 — Optional & Keyword Args

Defaults fill missing values; keywords label what you override.

SCSS
@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;
  }
}

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

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

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

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

How It Works

  1. Passing 0 sets $x; $y keeps 50%.
  2. Keyword $radius: 4px makes the intent obvious.
  3. Defaults can reference earlier arguments in more advanced APIs.
  4. Renaming public args can break callers — migrate carefully.

Example 4 — Content Blocks

Callers inject styles where the mixin places @content.

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

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

How It Works

  1. The mixin owns the selector wrapper.
  2. The caller owns the hover styles in a block.
  3. @content injects that block in place.
  4. Great for media-query helpers and interaction wrappers.

Example 5 — Argument Lists (...)

Accept any number of extra selectors after a fixed first argument.

SCSS
@use "sass:list";

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

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

How It Works

  1. Everything after 150px lands in $selectors.
  2. The loop emits one rule per selector.
  3. Offsets stack by multiplying the index by $height.
  4. You can also spread a list: @include order(150px, $list...).

Edge Cases & Pitfalls

Most mixin bugs are wrong tool choice, content scope, or renaming public arguments.

function

Need a value? Use @function

Mixins emit styles. If you only need a computed length or color, return it from a function instead.

content

@content is lexically scoped

The content block sees variables from the include site, not locals defined inside the mixin.

rename

Keyword args are public API

Renaming a parameter can break callers. Keep the old name temporarily and @warn during migration.

css

Mixin names never ship

Do not expect a class named after the mixin. Only generated declarations and selectors appear in CSS.

Sass Support

@mixin / @include are core Sass at-rules. Browsers never see them — only the CSS they expand into.

ImplementationStatus
Dart SassSupported (recommended)
LibSass / node-sassSupported (deprecated toolchain)
Ruby SassSupported (end-of-life)
BrowsersN/A — only see expanded CSS

Prefer Dart Sass for new projects. SCSS and indented syntax both support mixins (indented also has legacy = / + shorthand — prefer @mixin / @include).

Key Takeaways

  • Reuse styles: @mixin defines; @include expands.
  • Customize with args, defaults, keywords, and $args....
  • @content lets callers inject a style block into the mixin.
  • Emit CSS with mixins; compute values with functions.

One line: mixins are compile-time style templates you include wherever you need them.

Compile Notes

@mixin / @include never reach the browser. Conceptual flow:

flow.txt
1. Define @mixin (args / @content optional)
2. @include it in a selector or at the top level
3. Bind arguments; inject @content if provided
4. Expand generated CSS into the current context
5. Emit finished rules — mixin names are gone

Frequently Asked Questions

Mixins are reusable groups of styles defined with @mixin and inserted with @include. They help you avoid non-semantic utility classes and share style collections in libraries.
Write @mixin reset-list { … } then @include reset-list; inside a style rule (or at the top level). Hyphens and underscores in names are treated as identical.
Yes. Declare them after the name: @mixin rtl($property, $ltr-value, $rtl-value). Pass the same number of values when you @include, or use defaults and keyword arguments.
@content injects a block of styles passed by the caller into the mixin. Write @include hover { … } and place @content; where those styles should appear.
If the last parameter ends in ..., extra positional arguments become a list (an argument list). You can also pass a list or map followed by ... into an @include.
No. Mixins are compile-time only. The mixin name never appears in CSS—only the styles they generate.

Next: Sass @function Rule

Reusable value helpers that return SassScript results.

Sass @function Rule →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful