Sass @mixin and @include

Beginner
⏱️ 14 min read
📚 Updated: Jul 2026
🎯 5 Examples
@content · args…

What You’ll Learn

Sass mixins let you define styles once and reuse them anywhere with @include. This page covers arguments, defaults, keyword args, argument lists, @content blocks, and five compiled examples.

01

Define

@mixin

02

Use

@include

03

Args

Required / optional

04

Keywords

$name: value

05

Content

@content

06

Practice

5 examples

What Are Mixins?

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

  • Defined with @mixin name { … } or @mixin name($args…) { … }.
  • Included with @include name or @include name($args…).
  • Names cannot begin with --.
  • Hyphens and underscores are identical: reset-list = reset_list.
  • Mixin names never appear in CSS—only the styles they generate.
💡
Beginner tip

Think of a mixin as a reusable recipe card. @mixin writes the recipe; @include cooks it into the current selector.

📝 Syntax

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

nav ul {
  @include reset-list;
}

@mixin square($size, $radius: 0) {
  width: $size;
  height: $size;
  @if $radius != 0 {
    border-radius: $radius;
  }
}

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

🔢 Arguments

Official docs: arguments let you customize a mixin each time it is included. Declare variable names in parentheses after the mixin name, then pass matching SassScript expressions in @include.

Optional arguments

Give a default with $name: value. Callers can omit that argument. Defaults can be any expression and may refer to earlier arguments.

Keyword arguments

Pass by name: @include square(100px, $radius: 4px). Especially helpful for booleans and multiple optional values.

⚠️
Renaming args

Because any argument can be passed by name, renaming a parameter can break callers. Keep old names as optional aliases for a while if you must rename.

🔀 Taking Arbitrary Arguments

Official docs: if the last parameter ends in ..., extra positional arguments become a list (an argument list).

  • Pass a list with $list... to expand positional args.
  • Pass a map with $map... to expand keyword args.
  • Use meta.keywords($args) to read extra keyword arguments as a map.
  • Forward everything to another mixin with @include other($args...).

📄 Content Blocks (@content)

Official docs: a mixin can take an entire block of styles. Declare @content in the mixin body; callers pass styles in braces after @include.

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

.button {
  border: 1px solid black;
  @include hover {
    border-width: 2px;
  }
}
  • A mixin may include @content more than once.
  • Content blocks are lexically scoped—they see variables from the include site, not from inside the mixin.
  • Pass values into the block with @content($args…) and accept them with @include … using ($args…) (Dart Sass 1.15+).

📦 Mixins With @use

In modern Sass, put mixins in a partial and load them with a namespace:

styles.scss
// _buttons.scss
@mixin primary {
  background: #222;
  color: #fff;
}

// style.scss
@use "buttons";

.cta {
  @include buttons.primary;
}

⚡ Quick Reference

GoalCode
Define@mixin name { … }
Include@include name;
With args@include rtl(float, left, right);
Defaults@mixin x($a, $b: 50%) { … }
Keywords@include square(100px, $radius: 4px);
Rest args@mixin order($h, $sels...) { … }
Content block@include hover { … } + @content
From a module@include buttons.primary;

Examples Gallery

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

📚 Getting Started

Reusable style bundles and parameterized helpers.

Example 1 — Basic Mixin

Compose mixins and include them into a selector.

styles.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

horizontal-list includes reset-list, then adds li rules. Everything expands under nav ul.

Example 2 — Arguments

Customize properties with positional arguments and interpolation.

styles.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

#{$property} builds the property name. The & selector places [dir=rtl] outside .sidebar.

📈 Defaults, Content & Rest Args

Flexible APIs for real components.

Example 3 — Optional & Keyword Args

Defaults fill missing values; keywords label what you override.

styles.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

Passing 0 sets $x; $y keeps its default 50%. The keyword $radius: 4px makes the intent obvious.

Example 4 — Content Blocks

Callers inject styles where the mixin places @content.

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

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

How It Works

The mixin owns the selector wrapper; the caller owns the hover styles. Great for media-query helpers and interaction wrappers.

Example 5 — Argument Lists (...)

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

styles.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

Everything after 150px lands in $selectors. The loop stacks each field by multiplying the index by $height.

🚀 Real-World Use Cases

  • Design-system primitives — buttons, cards, focus rings.
  • RTL helpers — flip properties with one include.
  • Responsive wrappers@content inside breakpoints.
  • Icon / image replacement — shared background text tricks.
  • Library APIs — ship mixins via @use / @forward.

🧠 How Compilation Works

1

Define a mixin

Write styles (and optional args / @content) once.

Source
2

Include it

Pass arguments and an optional content block at the call site.

Compile
3

Expand in place

Sass copies the generated CSS into the current selector context.

Emit
4

CSS ships

Browsers never see @mixin—only finished rules.

⚠️ Common Pitfalls

  • Expecting a CSS class — mixin names are not selectors.
  • Missing required args — every non-default parameter must be passed.
  • Content scope surprises@content cannot see mixin-local variables.
  • Overusing mixins for one-liners — a variable or plain CSS may be clearer.
  • Huge CSS output — including a large mixin everywhere duplicates rules.

💡 Best Practices

✅ Do

  • Name mixins for intent (horizontal-list, not styles1)
  • Use keyword args for booleans and optional knobs
  • Prefer @content for wrappers callers should customize
  • Ship mixins through @use namespaces in libraries
  • Keep argument lists short and documented

❌ Don’t

  • Use mixins as a substitute for semantic HTML/CSS
  • Rename public args without a migration path
  • Assume content blocks see mixin variables
  • Rely on indented = / + syntax in new SCSS
  • Duplicate giant mixins when a shared class would do

Key Takeaways

Knowledge Unlocked

Five things to remember about Sass mixins

Define once with @mixin, reuse with @include.

5
Core concepts
📦 02

Include

@include name

Use
🔢 03

Args

defaults + keywords

API
📄 04

Content

@content blocks

Inject
05

Output

CSS only

Compile

❓ 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.
Did you know?

Official Sass docs treat hyphens and underscores as the same in mixin names—so @include reset-list and @include reset_list call the same mixin.

Conclusion

@mixin and @include are the core way to reuse style recipes in Sass. Start simple, add arguments and @content as APIs grow, and load shared mixins through @use in modern projects.

Continue with @function or browse @use.

Next: Sass @function

Define reusable value helpers with @return, args, and argument lists.

@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.

5 people found this page helpful