Sass Media Query Mixin

Media queries are a gigantic pain in the ass especially when they’re scattered throughout your code base. This Sass @mixin attempts in a half-ass way to resolve that problem (for me personally) by keeping it DRY and defining once. There’s also a RubyGem called “Breakpoint” http://breakpoint-sass.com, however I desire a custom @mixin without the reliance of a dependency like a Gem to manage this for me.

I know this isn’t a blanket for everything and that it won’t solve the 99.99% of problems out there, but that isn’t the point. It becomes very tough over time (once again for me personally) to manage 8, 12, 16, 24 breakpoints for a project while keeping things meaningful and easily updated. In my opinion a project using over 8 breakpoints is 4 too many and needs some rethinking. Use my personal @media query @mixin at will or improve upon it.

// ==================================================
// $Variables
// ==================================================
// Supports 
// @media min-width
// @media max-width
// @media min-width and max-width

$viewport-increment: 0.1px; // customize to suite

// Desktop
$desktop: 1024px; // customize to suite
$pre-desktop: $desktop - $viewport-increment;

// Tablet
$tablet: 768px; // customize to suite
$pre-tablet: $tablet - $viewport-increment;

// Palm
$palm: 640px; // customize to suite
$post-palm: $palm + $viewport-increment;

// Constraints
$min: min-width;
$max: max-width;


// ==================================================
// $Media Query @Mixin
// ==================================================

@mixin mediaQuery($constraint, $viewport1, $viewport2: null) {

  @if $constraint == $min {

    @media screen and ($min: $viewport1) {
      @content;
    }

  } @else if $constraint == $max {

    @media screen and ($max: $viewport1) {
      @content;
    }

  } @else {

    @media screen and ($min: $viewport1) and ($max: $viewport2) {
      @content;
    }

  }

}


// ==================================================
// The Implementation!
// ==================================================

p {
  @include mediaQuery($max, $palm) {
    font-size: 75%;
  }

  @include mediaQuery(null, $post-palm, $pre-tablet) {
    font-size: 87.5%;
  }

  @include mediaQuery($min, $tablet) {
    font-size: 90%;
  }
  
  @include mediaQuery($min, $desktop) {
    font-size: 108.75%;
  }
}

Output

@media screen and (max-width: 640px) {
  p {
    font-size: 75%;
  }
}

@media screen and (min-width: 640.1px) and (max-width: 767.9px) {
  p {
    font-size: 87.5%;
  }
}

@media screen and (min-width: 768px) {
  p {
    font-size: 100%;
  }
}

@media screen and (min-width: 1024px) {
  p {
    font-size: 108.75%;
  }
}

Codepen

// ==================================================
// $Variables
// ==================================================
// Supports 
// @media min-width
// @media max-width
// @media min-width and max-width

$viewport-increment: 0.1px; // customize to suite

// Desktop
$desktop: 1024px; // customize to suite
$pre-desktop: $desktop - $viewport-increment;

// Tablet
$tablet: 768px; // customize to suite
$pre-tablet: $tablet - $viewport-increment;

// Palm
$palm: 640px; // customize to suite
$post-palm: $palm + $viewport-increment;

// Constraints
$min: min-width;
$max: max-width;


// ==================================================
// $Media Query @Mixin
// ==================================================

@mixin mediaQuery($constraint, $viewport1, $viewport2: null) {

  @if $constraint == $min {

    @media screen and ($min: $viewport1) {
      @content;
    }

  } @else if $constraint == $max {

    @media screen and ($max: $viewport1) {
      @content;
    }

  } @else {

    @media screen and ($min: $viewport1) and ($max: $viewport2) {
      @content;
    }

  }

}


// ==================================================
// The Implementation!
// ==================================================

p {
  @include mediaQuery($max, $palm) {
    font-size: 75%;
  }

  @include mediaQuery(null, $post-palm, $pre-tablet) {
    font-size: 87.5%;
  }
 
  @include mediaQuery($min, $tablet) {
    font-size: 100%;
  }
  
  @include mediaQuery($min, $desktop) {
    font-size: 108.75%;
  }
}

See the Pen %= penName %> by Dennis Gaebel (@grayghostvisuals) on CodePen

Resources

GrayGhost

Web Development & Design, Technical Writing, Interaction Design, Open Source Maker & Contributor. Helping Create A Better Web. http://grayghostvisuals.com.
  1. Very nice! I’ve been trying to come up with a standalone mixin for a while, but digging through Susy or Compass gets pretty messy pretty fast.
    I’ll give this one a shot and see how it goes.
    Cheers

    1. Thanks Carson. Definitely no silver bullet, but for major layout shifts it makes updating/changing breakpoints a cinch.

  2. Elegant solution! I’m just curious about how you handle IE6-8 support (not that anyone wants to support it).

    Breakpoint provides a fallback class so that the media-queries don’t load in IE. Do you have a technique that you use? Perhaps a polyfill like Respond.js instead? Great site!

    1. Great question Matt. When the context requires such a case I load slight bits of typographic styling so content is accessible via conditional comments like this…

      <!--[if lte IE 8]>
      <link rel="stylesheet" href="css/ie8-styles.css">
      <![endif]-->
      <!--[if gt IE 8]><!-->
      <link rel="stylesheet" href="css/styles.css">
      <!--<![endif]-->

      Since IE8 won’t get served styles.css it won’t get the super advanced stuff. In my case I’m using typography when I can. Of course context is everything, but hopefully the approach is conveyed intelligently on my part.

      Another method would be to develop “mobile first” and place all your larger screen sizes within a @media query. With this approach IE8 doesn’t understand @media and only gets the “small screen” styling. I’ll also add that it’s good form to always feature test CSS support as you’re developing no matter what.

      1. Thanks, Dennis. Again, great solutions. I’m going to try this approach on my next project as I too am trying to move away from depending on Breakpoint.

Leave a Reply

Your email address will not be published. Required fields are marked *

show formatting examples
<pre class="language-[markup | sass | css | php | javascript | ruby | clike | bash]"><code>
…code example goes here…
</code></pre>

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Comment Preview

  1. John Doe shouted this comment preview:
    2013/09/26