Media Mixin

I've seen lots of ways of handling media queries in Sass, but so far my favorite has been to use a single map of breakpoints and a simple media mixin.

$breakpoints: (
  xs: 20rem,  //  320px
  sm: 36rem,  //  576px
  md: 48rem,  //  768px
  lg: 62rem,  //  992px
  xl: 75rem   // 1200px
);

@mixin media($from, $to: null) {
  $min: map-get($breakpoints, $from);
  $max: if(
    map-has-key($breakpoints, $to),
    map-get($breakpoints, $to) - 0.001,
    null
  );

  @if $min and $max {
    @media (min-width: $min) and (max-width: $max) {
      @content;
    }
  } @else if $min {
    @media (min-width: $min) {
      @content;
    }
  } @else if $max {
    @media (max-width: $max) {
      @content;
    }
  }
}

Using the mixin is simple. It takes two parameters to specify the range for the media query.

@include media(sm, lg) {
    // styles apply between the small and large breakpoints
}

If the second parameter is omitted, the media query will apply using the given breakpoint as a minimum width.

@include media(md) {
    // styles apply above the medium breakpoint
}

This helps to have declarative, mobile-first media queries:

.example {
    padding: 0 15px;

    @include media(sm, md) {
        margin: 0 auto;
        padding: 0;
        width: 480px;
    }

    @include media(md) {
        width: 600px;
    }
}

If null is passed as the first parameter, the media queries apply using the given breakpoint as a maximum width.

@include media(null, md) {
    // styles apply below the medium breakpoint
}

I've set up a working example of this media query mixin in use on Code Pen.