Responsive Web Design creations often exist over several different breakpoints. Managing those breakpoints is not always easy. Using them and updating them can sometimes be tedious. Hence the need for a mixin to handle breakpoint configuration and usage.
Simple version
First you need a map of breakpoints, associated to names.
$breakpoints: (
'small': 767px,
'medium': 992px,
'large': 1200px
) !default;
Then, the mixin will use this map.
/// Mixin to manage responsive breakpoints
/// @author Kitty Giraudel
/// @param {String} $breakpoint - Breakpoint name
/// @require $breakpoints
@mixin respond-to($breakpoint) {
// If the key exists in the map
@if map-has-key($breakpoints, $breakpoint) {
// Prints a media query based on the value
@media (min-width: map-get($breakpoints, $breakpoint)) {
@content;
}
}
// If the key doesn't exist in the map
@else {
@warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. "
+ "Available breakpoints are: #{map-keys($breakpoints)}.";
}
}
Usage:
.selector {
color: red;
@include respond-to('small') {
color: blue;
}
}
Result:
.selector {
color: red;
}
@media (min-width: 767px) {
.selector {
color: blue;
}
}
Advanced version
The simple version only makes it possible to use min-width
media queries. To use more advanced queries, we can tweak our initial map and mixin a bit.
$breakpoints: (
'small': ( min-width: 767px ),
'medium': ( min-width: 992px ),
'large': ( min-width: 1200px )
) !default;
/// Mixin to manage responsive breakpoints
/// @author Kitty Giraudel
/// @param {String} $breakpoint - Breakpoint name
/// @require $breakpoints
@mixin respond-to($breakpoint) {
// If the key exists in the map
@if map-has-key($breakpoints, $breakpoint) {
// Prints a media query based on the value
@media #{inspect(map-get($breakpoints, $breakpoint))} {
@content;
}
}
// If the key doesn't exist in the map
@else {
@warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. "
+ "Available breakpoints are: #{map-keys($breakpoints)}.";
}
}
Usage
.selector {
color: red;
@include respond-to('small') {
color: blue;
}
}
Result
.selector {
color: red;
}
@media (min-width: 767px) {
.selector {
color: blue;
}
}
Really enjoying this mixin, however i’m wondering how i might use this with retina devices. Is it as simple as adding another variable, or do i need to add an additional if statement?
Very helpful, thanks for sharing!
But what if I have my breakpoints as nested map keys? The ‘map-has-key’ only works at top level ad as far as I understood I am not allowed to put a function inside a mixin.
example of a map:
Is it overengineering?
@Jack, why not just separate the $structure variable into two different variables: $containers and $breakpoints?