Episode 1 — Fundamentals / 1.7 — Working With SASS
1.7.e — Mixins
In one sentence: A mixin is a reusable block of CSS declarations you define once with
@mixinand stamp into any rule set with@include— like a function that outputs CSS instead of returning a value.
Navigation: ← 1.7.d — Partials & Imports · 1.7.f — Inheritance & Extends →
1. Basic syntax
// Define
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
// Use
.hero {
@include flex-center;
height: 100vh;
}
Compiles to:
.hero {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
The mixin's declarations are copied into every @include site. This is different from @extend, which groups selectors (see 1.7.f).
2. Mixins with arguments
@mixin button($bg, $color: white) {
background: $bg;
color: $color;
padding: 0.5rem 1rem;
border: none;
border-radius: 0.25rem;
cursor: pointer;
}
.btn-primary {
@include button(#3b82f6);
}
.btn-danger {
@include button(#ef4444, #fff);
}
| Feature | Syntax |
|---|---|
| Required argument | $bg — must be passed |
| Default value | $color: white — used if not passed |
| Named arguments | @include button($bg: red, $color: black) — order-independent |
3. @content — passing blocks
@content lets you inject arbitrary CSS into the middle of a mixin. This is how responsive breakpoint mixins work:
@mixin respond-to($breakpoint) {
@if $breakpoint == 'md' {
@media (min-width: 768px) { @content; }
} @else if $breakpoint == 'lg' {
@media (min-width: 1024px) { @content; }
} @else if $breakpoint == 'xl' {
@media (min-width: 1280px) { @content; }
}
}
.sidebar {
width: 100%;
@include respond-to('md') {
width: 250px;
}
@include respond-to('lg') {
width: 300px;
}
}
Compiles to:
.sidebar { width: 100%; }
@media (min-width: 768px) { .sidebar { width: 250px; } }
@media (min-width: 1024px) { .sidebar { width: 300px; } }
4. Common real-world mixins
Responsive breakpoints (map-driven)
$breakpoints: (
'sm': 640px,
'md': 768px,
'lg': 1024px,
'xl': 1280px,
);
@mixin breakpoint($name) {
$value: map-get($breakpoints, $name);
@media (min-width: $value) {
@content;
}
}
Typography shorthand
@mixin text($size, $weight: 400, $line-height: 1.5) {
font-size: $size;
font-weight: $weight;
line-height: $line-height;
}
h1 { @include text(2.5rem, 700, 1.2); }
Truncate text
@mixin truncate($lines: 1) {
@if $lines == 1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} @else {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
.card__title { @include truncate(2); }
Visually hidden (accessible hide)
@mixin visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.sr-only { @include visually-hidden; }
5. Mixins vs functions
@mixin | @function | |
|---|---|---|
| Purpose | Output CSS declarations | Compute and return a value |
| Used with | @include | Inline in a property value |
| Returns | Nothing (emits CSS) | A value via @return |
| Example | @include flex-center; | width: rem(16); |
Rule of thumb: If you need declarations (property: value pairs), use a mixin. If you need a computed value, use a function.
6. Mixins vs extends
@mixin + @include | @extend | |
|---|---|---|
| Output | Declarations copied to each include site | Selectors grouped — shared rule |
| Arguments | Yes | No |
@content blocks | Yes | No |
| In media queries | Works everywhere | Cannot extend across media query boundaries |
| Output size | Can be larger (duplicated declarations) | Smaller when many selectors share rules |
Use mixins by default. Reach for @extend only when you have many selectors sharing identical static rules and you understand the pitfalls.
7. Organizing mixins with @use
// abstracts/_mixins.scss
@mixin flex-center { … }
@mixin breakpoint($name) { … }
@mixin truncate($lines: 1) { … }
// components/_cards.scss
@use '../abstracts/mixins';
.card {
@include mixins.flex-center;
@include mixins.truncate(2);
}
Namespacing prevents collisions — you always know where a mixin came from.
8. Key takeaways
@mixindefines a reusable block of CSS;@includestamps it into a rule.- Mixins accept arguments with optional default values and support named arguments.
@contentlets you pass arbitrary CSS blocks into a mixin — the foundation of responsive breakpoint patterns.- Use mixins for CSS declarations, functions for computed values.
- Prefer mixins over
@extendin most cases — they are more flexible and predictable.
Explain-It Challenge
Explain without notes:
- How does
@contentwork inside a mixin — give a breakpoint example. - Why would you choose a mixin over
@extendfor a button variant? - Write a mixin from memory that accepts a background color and optional text color with a default.
Navigation: ← 1.7.d — Partials & Imports · 1.7.f — Inheritance & Extends →