Product Design Lessons
Intro to Foundation | Lesson #40
Master Media Queries With Sass
Learn to edit multiple media queries with a few Sass variables.
No media query is an island unto itself. Several often work together to create the appropriate styles for different scenarios — smartphones, tablets and desktop browsers, and even different screen orientations. You have to worry about conflicting ranges. You have to write redundant code. You have to hunt for queries through dozens or hundreds of lines in CSS. Overall, media queries in complex products can be a pain.
But they don't have to be. Sass makes media queries a snap with very little setup. Here's how you can use Sass variables to master media queries.
Look at regular media queries
Here's a typical setup in plain CSS:
@media screen and (max-width:40em) { … }
@media screen and (min-width: 40.063em)
and (max-width: 64em) { … }
@media screen and (min-width: 64.063em)
and (max-width: 120em) { … }
@media screen and (min-width: 120.063em) { … }
This code creates four ranges: 0–40em, 40.063–64em, 64.063–120em, and 120.063+ em. Trouble is, each { … } could stand for hundreds of lines of CSS. Adjusting widths from 40em to, say, 42 poses a problem. This is what we want Sass to handle for us.
1. Define your ranges
A range is the space between breakpoints — while a breakpoint might be 10em, for example, 10–20em defines everything between 10 and 20. In this case, our ranges look like this:
$small-range: ( 0em, 40em );
$medium-range: ( 40.063em, 64em );
$large-range: ( 64.063, 120em );
We prevent overlaps at each breakpoint by adding 0.063 — approximately one pixel when the default font size is 16pt — to each minimum width.
Above: Overlaps occur when two ranges, like 0–40 and 40–80, have a pixel of overlap. At that point, browsers don't know which set of rules to apply. When we make one just slightly different — in this case adding 0.063em — ranges become unambiguous.
2. Add ranges to media queries
The next step sets up ranges to become media queries.
$small-query: "#{$screen} and
(max-width: #{upper-bound($small-range)})";
$medium-query: "#{$screen}
and (min-width:#{lower-bound($medium-range)})
and (max-width:#{upper-bound($medium-range)})";
$large-query: "#{$screen}
and (min-width:#{lower-bound($large-range)})
and (max-width:#{upper-bound($large-range)})";
3. Add code to media queries
Notice that this isn't CSS yet — browsers don't read SCSS itself. We're just setting up the code for the queries themselves, which we define next:
@media screen and #{$small-query} { … }
@media screen and #{$medium-query} { … }
@media screen and #{$large-query} { … }
When compiled you'll get:
@media only screen
and (max-width: upper-bound(0em, 42em)) { … }
@media only screen
and (min-width: lower-bound(42.063em, 64em))
and (max-width: upper-bound(42.63em, 64em)) { … }
@media only screen
and (min-width: lower-bound(64.063em, 90em))
and (max-width: upper-bound(64.063em, 90em)) { … }
4. Adjust on the fly
Let's say we decide that 0–40em isn't right. Maybe we want, say, 0–42em instead. Using the first variables we defined, you can change both the small range (0–40em) and bump up the medium range to accommodate the change.
$small-range: ( 0em, 42em );
$medium-range: ( 42.063em, 64em );
$large-range: ( 64.063, 120em );
This one change will result these media queries:
@media only screen and (max-width: 42em)) { … }
@media only screen
and (min-width: 42.063em)
and (max-width: 42.063em, 64em) { … }
@media only screen
and (min-width: 64.063em)
and (max-width: 64.63em) { … }
Actually, when we think mobile-first, the first media query is redundant — all styles should apply except for medium and large screens. But the small query is helpful for debugging.
A practical example
Let's apply this to a real site. Pure Fix Bikes has several breakpoints that we could use Foundation's medium- and large-block grids to create.
Above: We could use the medium block grid to arrange images in two different rows.
Above: Meanwhile the large block grid creates a different layout arrangement, which adds even more non-semantic code to the page.
To make this semantic, we start by creating two sets of elements:
.menu { }
.item-list { }
Into that we add Foundation's block grid:
.menu {
@include block-grid(1);
}
.item-list {
@include block-grid(1);
}
These includes will create a single-block-wide layout, which works well on mobile devices. Next we add Foundation's built-in $medium-up media query to override that in medium-sized screens:
.menu {
@include block-grid(1);
@media #{$medium-up} {
@include block-grid(2);
}
}
.item-list {
@include block-grid(1);
@media #{$medium-up} {
@include block-grid(3);
}
}
Finally, we add a media query to push the menu to four items in large viewports. (Remember that the item-list remains three blocks wide.)
.menu {
text-align: center;
@include block-grid(1);
@media #{$medium-up} {
@include block-grid(2);
}
@media #{$large-up} {
@include block-grid(4);
}
}
.item-list {
@include block-grid(1);
@media #{$medium-up} {
@include block-grid(3);
}
}
And that's it. The more complicated a product's CSS becomes, the more important variables are. This technique keeps you from digging through hundreds of lines to keep track of media queries' ranges, especially when you organize your SCSS into parts that use the same query values repeatedly.
About the instructor
Ben Gremillion is a Design Writer at ZURB. He started his career in newspaper and magazine design, saw a digital future, and learned HTML in short order. He facilitates the ZURB training courses.
Product Design Lessons, Direct to Your Inbox
We're just getting started, so sign up and we'll keep you in the know with our product design lessons. No spam here.