Media queries in Sass
Create media queries in Sass by using maps, functions, mixins and variables.
We can use media queries for targeting a block of CSS if a certain condition is true. We have a full range of media queries for specific characteristics at our disposal.
In this guide, we'll be looking at Bootstrap's approach to media queries using Sass
and how to target specific screen sizes for our layouts.
Get the code:metal:
Maps
Maps represent an association between keys
and values
. This is handy to collect values into groups. Maps must be surrounded by parentheses and comma-separated. The !default
flag won't allow value reassignment.
Breakpoints defined as a map
from small to large.
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, ) !default;
Maps are mostly manipulated by functions. map-get
returns the value associated with the given key. If the map doesn't have such a key, it returns null
.
map-get($map, $key);
Function Directives
First, we'll be creating some utility functions to later use them on our mixins to evaluate the condition we are targeting.
We can define our own functions in sass
and use them in any value or script context. Functions can access any globally defined variables or accept arguments just like a mixin.
breakpoint-min <br>
The breakpoint-min
function uses map-get
to return the minimum breakpoint width. Null for the smallest (first) breakpoint.
The $name
argument defines the breakpoint size and $grid-breakpoints
is a global variable used as the $breakpoints
argument by default.
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) { $min: map-get($breakpoints, $name); @return if($min != 0, $min, null); }
breakpoint-next <br>
The breakpoint-next
uses map-keys($map)
returns a list of all keys in a map and index
returns the position of a pair in a map. The result is the name of the next breakpoint, or null for the last breakpoint.
@function breakpoint-next( $name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints) ) { $n: index($breakpoint-names, $name); @return if( $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null ); }
breakpoint-max <br>
breakpoint-max
return the maximum breakpoint width. Null for the largest (last) breakpoint.
The maximum value is calculated as the minimum of the next one less 0.02px
to work around the limitations of min- and max- prefixes and viewports with fractional widths.
Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) { $next: breakpoint-next($name, $breakpoints); @return if($next, breakpoint-min($next, $breakpoints) - 0.02px, null); }
Mixins
Mixins allow us define styles that can be re-used throughout our stylesheets. Let's define the breakpoint mixins for our media queries.
@mixin screen-up() { ... } @mixin screen-down() { ... } @mixin screen-only() { ... } @mixin screen-between() { ... }
When using the breakpoint mixin, we'll need to pass the breakpoint width or widths we are targeting. For Example:
@include screen-up(sm) { ... } @include screen-between(md, xl) { ... }
Bootstrap uses the mobile first approach. We don't need a query for the smallest breakpoint.
screen-up
This mixin targets @media
of at least the minimum breakpoint width. It makes the @content
apply to the given breakpoint and wider.
@mixin screen-up($name, $breakpoints: $grid-breakpoints) { $min: breakpoint-min($name, $breakpoints); @if $min { @media (min-width: $min) { @content; } } @else { @content; } }
screen-down
This mixin targets @media
of at most the maximum breakpoint width. It makes the @content
apply to the given breakpoint and narrower. There is no query for the largest breakpoint.
@mixin screen-down($name, $breakpoints: $grid-breakpoints) { $max: breakpoint-max($name, $breakpoints); @if $max { @media (max-width: $max) { @content; } } @else { @content; } }
screen-only
This mixin targets @media
between the breakpoint's minimum and maximum widths. It makes the @content
apply only to the given breakpoint, not viewports any wider or narrower.
@mixin screen-only($name, $breakpoints: $grid-breakpoints) { $min: breakpoint-min($name, $breakpoints); $max: breakpoint-max($name, $breakpoints); @if $min != null and $max != null { @media (min-width: $min) and (max-width: $max) { @content; } } @else if $max == null { @include screen-up($name, $breakpoints) { @content; } } @else if $min == null { @include screen-down($name, $breakpoints) { @content; } } }
screen-between
This mixin targets @media
that spans multiple breakpoint widths. It makes the @content
apply between the min and max breakpoints.
@mixin screen-between($lower, $upper, $breakpoints: $grid-breakpoints) { $min: breakpoint-min($lower, $breakpoints); $max: breakpoint-max($upper, $breakpoints); @if $min != null and $max != null { @media (min-width: $min) and (max-width: $max) { @content; } } @else if $max == null { @include screen-up($lower, $breakpoints) { @content; } } @else if $min == null { @include screen-down($upper, $breakpoints) { @content; } } }
How to use them
Media queries mixins:<br>
screen-up, screen-down, screen-only, screen-between
.
Target sizes:<br>
xs, sm, md, lg, xl
.
// example: apply to target (lg) and wider @include screen-up(lg) { .custom-class { color: red; } } // size range @include screen-between(md, xl) { ... }