Skip to content

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: 20em,  //  320px
  sm: 36em,  //  576px
  md: 48em,  //  768px
  lg: 62em,  //  992px
  xl: 75em   // 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.