Skip to content

Sass Mixins — Complete Guide

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Sass Mixins. We cover key concepts, practical examples, and best practices to help you master this topic.

Sass mixins define reusable style blocks with arguments, default values, variable arguments, and content blocks for DRY maintainable CSS.

What You'll Learn

  • Defining and including mixins
  • Mixin arguments and default values
  • Keyword arguments
  • Variable arguments (...)
  • Content blocks with @content
  • When to use mixins vs extends
  • Best practices for mixin organization

Why It Matters

  • Mixins prevent repeating common patterns
  • Parameters make mixins flexible
  • Content blocks enable component customization
  • Mixins reduce update overhead

Real-World Use

  • A button mixin generates multiple button variants
  • A responsive mixin generates media queries consistently
  • A typography mixin applies consistent font styles
  • A vendor prefix mixin adds browser prefixes
flowchart LR
  A[Sass Mixin] --> B[Definition]
  A --> C[Parameters]
  A --> D[Content Block]
  B --> E[Include in selector]
  C --> F[Flexible output]
  D --> G[Custom content]

Working with Mixins

Code Example: Basic Mixin

// Define a mixin
@mixin button-base {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 1.5rem;
    border: none;
    border-radius: 4px;
    font-size: 1rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    min-height: 44px;
    text-decoration: none;
}

// Use the mixin
.btn-primary {
    @include button-base;
    background: #0066CC;
    color: #fff;

    &:hover {
        background: darken(#0066CC, 10%);
    }
}

.btn-secondary {
    @include button-base;
    background: #6c757d;
    color: #fff;

    &:hover {
        background: darken(#6c757d, 10%);
    }
}

Expected output: Both .btn-primary and .btn-secondary include the base button styles from the mixin. The mixin reduces duplication of the common button properties.

Code Example: Mixins with Arguments

// Mixin with parameters and defaults
@mixin button-variant($bg, $color: #fff, $hover-bg: null) {
    background: $bg;
    color: $color;

    // If hover-bg is not provided, darken the background
    $hover: if($hover-bg, $hover-bg, darken($bg, 10%));

    &:hover {
        background: $hover;
    }

    &:focus-visible {
        outline: 3px solid rgba($bg, 0.4);
        outline-offset: 2px;
    }
}

@mixin font-size($size, $line-height: 1.5) {
    font-size: $size;
    line-height: $line-height;
}

@mixin spacing($padding: 1rem, $margin: 0) {
    padding: $padding;
    margin: $margin;
}

// Usage
.btn-primary {
    @include button-variant(#0066CC);
}

.btn-success {
    @include button-variant(#28a745, #fff, #1e7e34);
}

.btn-outline {
    @include button-variant(transparent, #0066CC, #e6f2ff);
}

.alert {
    @include font-size(1rem, 1.6);
    @include spacing(1rem, 1rem 0);
}

Expected output: Each button variant passes different arguments to the mixin. Default values handle common cases. Callers can override defaults explicitly.

Code Example: Content Blocks with @content

// Mixin that accepts a content block
@mixin respond-to($breakpoint) {
    $value: map-get($breakpoints, $breakpoint);

    @if $value {
        @media (min-width: $value) {
            @content;  // Custom content inserted here
        }
    } @else {
        @warn "Unknown breakpoint: #{$breakpoint}.";
    }
}

@mixin card($padding: 1.5rem, $radius: 8px) {
    background: #fff;
    border: 1px solid #eee;
    border-radius: $radius;
    padding: $padding;

    @content;  // Allow additional custom styles
}

// Usage with content blocks
.featured-card {
    @include card(2rem, 12px) {
        box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        border-color: #0066CC;
    }
}

.simple-card {
    @include card;
}

// Responsive mixin with content
.sidebar {
    @include respond-to('md') {
        width: 300px;
        float: right;
    }

    @include respond-to('lg') {
        width: 350px;
    }
}

Expected output: The @content directive allows callers to inject custom styles inside the mixin. The respond-to mixin generates media queries consistently across the project.

Code Example: Variable Arguments and Loops

// Variable arguments (...)
@mixin box-shadow($shadows...) {
    -webkit-box-shadow: $shadows;
    -moz-box-shadow: $shadows;
    box-shadow: $shadows;
}

.element {
    @include box-shadow(0 2px 4px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.05));
}

// Multiple arguments with variable
@mixin transition($properties...) {
    $transitions: ();
    @each $prop in $properties {
        $transitions: append($transitions, $prop 0.3s ease, comma);
    }
    transition: $transitions;
}

.element {
    @include transition(opacity, transform, background);
}

// Mixin generating utility classes
@mixin generate-spacing($prefix, $property, $values) {
    @each $key, $value in $values {
        .#{$prefix}-#{$key} {
            #{$property}: $value;
        }
    }
}

$spacings: (
    '0': 0,
    'xs': 4px,
    'sm': 8px,
    'md': 16px,
    'lg': 24px,
    'xl': 32px
);

@include generate-spacing('mt', 'margin-top', $spacings);
@include generate-spacing('mb', 'margin-bottom', $spacings);
@include generate-spacing('pt', 'padding-top', $spacings);
@include generate-spacing('pb', 'padding-bottom', $spacings);

Expected output: Variable arguments accept any number of values. The generate-spacing mixin creates utility classes (mt-md, mb-lg) from a spacing map, significantly reducing manual repetition.

Common Mistakes

  1. Using mixins when a simple class would do — If a mixin has no parameters and is used once, consider using @extend or a class instead.
  2. Creating mixins that output too much CSS — Mixin output is duplicated every time it is included. For large blocks of static styles, use @extend.
  3. Not using default parameter values — Defaults make mixins easier to use. Only require parameters that must always be customized.
  4. Over-abstraction — Not every repeated property needs a mixin. Three similar buttons do not necessarily need a mixin.
  5. No responsiveness in mixins — Mixins should be responsive-friendly. Accept parameters for breakpoint-specific values.
  6. Forgetting to use @content for customization — Mixins without @content force callers to override styles after the include.
  7. Not documenting mixins — Complex mixins with many parameters should document their purpose, parameters, and defaults.

Practice Questions

  1. What is the syntax for defining a mixin? @mixin name { ... } and @include name to use it.
  2. How do you pass a content block to a mixin? Use @content inside the mixin definition and pass the block inside the @include call.
  3. What is the difference between @mixin and @extend? @mixin copies styles each time (duplication). @extend groups selectors (no duplication). Use mixins for parameterized styles, extends for shared static styles.
  4. What does the ... syntax do in mixin parameters? It accepts variable arguments (any number of values) as a list.

FAQ

Can I use @content multiple times in a mixin?

Yes. @content can appear multiple times at different positions within the mixin. Each call injects the same content block at that position.

Should I put mixins in separate files?

Yes. Store mixins in _mixins.scss grouped by category (buttons, typography, layout, responsive). Import them where needed.

Can I call a mixin inside another mixin?

Yes. Mixins can include other mixins. This creates composable, layered abstractions.

Mini Project

Create a _mixins.scss partial with 10 reusable mixins: (1) button-variant for button colors, (2) respond-to for responsive breakpoints, (3) font-size with line-height, (4) visually-hidden for screen-reader-only content, (5) truncate for text overflow, (6) focus-ring for accessible focus styles, (7) card-base for card components, (8) grid-responsive for auto-fit grids, (9) aspect-ratio for embed containers, and (10) generate-utilities for spacing utility classes. Build a sample page that uses all mixins. Demonstrate how changing one mixin call updates all instances.

What's Next

Continue with Lesson 6: Sass Functions to learn how to create and use custom functions.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro