A Responsive Mixin Library
Build a small, ergonomic set of breakpoint mixins — min-width, max-width and between — from one map.
Every serious project ends up needing responsive helpers. Rather than scatter raw @media queries, centralise breakpoints in one map and expose a handful of @content mixins. Change a breakpoint once and the whole codebase follows.
The core mixin
@use 'sass:map';
$bp: ('md': 768px);
@mixin up($name) {
@media (min-width: map.get($bp, $name)) { @content; }
}
.nav { display: none; @include up('md') { display: flex; } }What a good library provides
up($name)— mobile-first, min-width. Your default.down($name)— max-width, using the breakpoint minus 0.02px to avoid overlap.between($a, $b)— a bounded range.- An
@errorguard so a typo'd breakpoint name fails the build.
Mobile-first (up) should be the habit: start with the small-screen styles unconditionally, then layer enhancements at each breakpoint.
Example
@use 'sass:map';
$breakpoints: (
'sm': 480px,
'md': 768px,
'lg': 1024px,
'xl': 1280px,
);
@function _bp($name) {
@if not map.has-key($breakpoints, $name) {
@error 'No breakpoint "#{$name}". Known: #{map.keys($breakpoints)}.';
}
@return map.get($breakpoints, $name);
}
@mixin up($name) {
@media (min-width: _bp($name)) { @content; }
}
@mixin down($name) {
@media (max-width: _bp($name) - 0.02px) { @content; }
}
@mixin between($min, $max) {
@media (min-width: _bp($min)) and (max-width: _bp($max) - 0.02px) {
@content;
}
}
.sidebar {
display: none; // mobile-first base
@include up('lg') { display: block; }
}
.promo {
@include between('md', 'lg') { flex-direction: row; }
}When to use it
- A team replaces ad-hoc media queries scattered across 50 component files with a small mixin library (bp.up, bp.down, bp.between) backed by one breakpoint map.
- A developer uses a between() mixin to target only tablets (768px–1024px) for a sidebar layout without writing the verbose two-condition media query by hand.
- A component library ships its breakpoint map as a !default variable so consumer projects can add or rename breakpoints without touching the mixin source.
More examples
Breakpoint map and up() mixin
A breakpoint map backed by !default drives an up() mixin that wraps any @content block in the correct min-width query.
@use 'sass:map';
$bps: (xs: 0, sm: 640px, md: 768px, lg: 1024px, xl: 1280px) !default;
@mixin up($bp) {
@media (min-width: map.get($bps, $bp)) { @content; }
}
.sidebar {
display: none;
@include up(md) { display: block; width: 260px; }
}down() and between() mixins
Adds a max-width down() mixin and a min-and-max between() mixin, completing a three-function responsive API from one breakpoint map.
@use 'sass:map';
@mixin down($bp) {
@media (max-width: map.get($bps, $bp) - 0.02px) { @content; }
}
@mixin between($lower, $upper) {
@media (min-width: map.get($bps, $lower))
and (max-width: map.get($bps, $upper) - 0.02px) { @content; }
}
.ad-banner {
@include between(sm, lg) { display: block; }
}Configuring breakpoints downstream
Overrides the library's default breakpoint map at @use time so the entire mixin library operates on the project's custom breakpoints.
// project/main.scss
@use 'responsive-lib' with (
$bps: (
sm: 600px,
md: 900px,
lg: 1200px,
xl: 1600px
)
);
.container {
@include responsive-lib.up(lg) { max-width: 1140px; }
}
Discussion