Breakpoint mixins that keep media queries consistent without burying your component logic three levels deep. The goal is responsive SCSS you can still read aloud..
Breakpoint map
Define breakpoints once:
$breakpoints: (
'sm': 30rem, // 480px
'md': 48rem, // 768px
'lg': 64rem, // 1024px
'xl': 80rem, // 1280px
);
Use em or rem for breakpoints where you can – they respect user font settings better than raw pixels.
A simple min-width mixin
@use 'sass:map';
@mixin bp-up($name) {
$width: map.get($breakpoints, $name);
@if $width {
@media (min-width: $width) {
@content;
}
} @else {
@warn 'Unknown breakpoint: #{$name}';
}
}
Usage keeps the default mobile-first styles outside the query:
.card-grid {
display: grid;
grid-template-columns: 1fr;
gap: $space-md;
@include bp-up('md') {
grid-template-columns: repeat(2, 1fr);
}
@include bp-up('lg') {
grid-template-columns: repeat(3, 1fr);
}
}
Max-width and between
@mixin bp-down($name) {
$width: map.get($breakpoints, $name);
@media (max-width: ($width - 0.02rem)) {
@content;
}
}
@mixin bp-between($from, $to) {
$min: map.get($breakpoints, $from);
$max: map.get($breakpoints, $to);
@media (min-width: $min) and (max-width: ($max - 0.02rem)) {
@content;
}
}
The tiny subtract avoids overlap glitches when min- and max-width queries meet at the same pixel.
Avoid mixin soup
Bad pattern – entire components defined only inside breakpoints:
// Hard to follow
.hero {
@include bp-up('md') {
@include bp-up('lg') {
padding: $space-2xl;
}
}
}
Better: write the component top to bottom, one breakpoint block at a time, smallest to largest. If a file needs more than two nested @include bp-up calls, split the component or simplify the layout.
Prefer container queries where fit
Breakpoints tune the viewport. Container queries tune the component’s parent – often the right tool for cards and sidebars. SCSS can wrap them the same way:
@mixin container-up($width) {
@container (min-width: #{$width}) {
@content;
}
}
.card {
container-type: inline-size;
@include container-up(25rem) {
display: flex;
gap: $space-md;
}
}
Native CSS nesting (see a later tutorial) can reduce mixin noise for simple queries. Breakpoint mixins still earn their keep for shared names and consistent units.
Try it
- Add a breakpoint map and
bp-upmixin to your abstracts folder. - Refactor one component from raw
@mediato the mixin. - Read the file aloud – if you lose the thread, flatten nesting.

