How to write media queries with SASS/SCSS

Let’s face facts: media queries can be a pain. They’re difficult to write and they tend to get duplicated a lot. Sass includes a few helpful features that make media queries easier to work with. This article will show you these tricks and how you can use them to simplify your stylesheets.

The Basics

Let’s take a look at a simple example.

p {
  font-size: 16px;
}

@media (min-width: 768px) and (max-width: 1023px) {
  p {
    font-size: 18px;
  }
}

@media (min-width: 1024px) {
  p {
    font-size: 20px;
  }
}

Here, we’ve set the font size of paragraphs to 16 pixels. When the viewport width is greater than or equal to 768 pixels, and less than or equal to 1023 pixels, the font size is 18 pixels. When the viewport is greater than or equal to 1024 pixels, the font size is 20 pixels.

Right away, you should be struck by how much code is required to do something as simple as responsive typography. As projects grow larger, the above style of writing media queries usually leads in one of two directions:

  • Media queries are hardcoded in the code and copied where they’re needed. If we want to change a media query, we have to do it in many places.
  • The project is split up by viewport sizes. It’s jarring and time-consuming to jump to multiple places to update a single element’s styles.

Shortening Things Up

Sass allows variables to be interpolated. This means that we can move our media queries into variables and reuse them.

$tablet: "(min-width: 768px) and (max-width: 1023px)";
$desktop: "(min-width: 1024px)";

p {
  font-size: 16px;
}

@media #{$tablet} {
  p {
    font-size: 18px;
  }
}

@media #{$desktop} {
  p {
    font-size: 20px;
  }
}

Now, we can use the $tablet and $desktop media queries anywhere in our project without duplicating code. However, it’s still annoying that our media queries are separate from the code they style. The Sass folks fixed this problem by allowing media queries to be nested.

$tablet: "(min-width: 768px) and (max-width: 1023px)";
$desktop: "(min-width: 1024px)";

p {
  font-size: 16px;

  @media #{$tablet} {
    font-size: 18px;
  }

  @media #{$desktop} {
    font-size: 20px;
  }
}

Mixins to the Rescue

The code above works, but it’s a bit difficult to read. We can clean it up by using Sass’s mixins. Mixins are groups of styles that can be reused throughout your code. One of the nifty features of mixins is they can use blocks of content. This lets us write mixins like this:

$tablet-width: 768px;
$desktop-width: 1024px;

@mixin tablet {
  @media (min-width: #{$tablet-width}) and (max-width: #{$desktop-width - 1px}) {
    @content;
  }
}

@mixin desktop {
  @media (min-width: #{$desktop-width}) {
    @content;
  }
}

Now, we can rewrite our example above to use these new mixins.

p {
  font-size: 16px;

  @include tablet {
    font-size: 18px;
  }

  @include desktop {
    font-size: 20px;
  }
}

We’re not just limited to device sizes. We can write media queries for many other useful things, such as Chris Coyier’s retina media query or a print media query.

@mixin retina {
  @media
    only screen and (-webkit-min-device-pixel-ratio: 2),
    only screen and (min--moz-device-pixel-ratio: 2),
    only screen and (-o-min-device-pixel-ratio: 2/1),
    only screen and (min-device-pixel-ratio: 2),
    only screen and (min-resolution: 192dpi),
    only screen and (min-resolution: 2dppx) {
    @content;
  }
}

@mixin print {
  @media print {
    @content;
  }
}

Wrapping Up

Media queries are great, and with Sass they can be even better. The next time you use one, remember these tricks to help make your code more readable and easier to maintain.

Source: https://davidwalsh.name/write-media-queries-sass