Updating My Sass Media Query Mixin

Back in April 2013, I wrote about my media query mixin and how I wanted to keep it simple yet adaptable to most of my needs.

I wanted it so that I can change from min-width to max-width easily, to also use height, to make sure it’s computed in ems and not be tied down to any variables. The last one still holds true. I believe we should be still adopting the Stephen Hay approach I mentioned in 2012:

“Start with the small screen first, then expand until it looks like shit. Time to insert a breakpoint!”

Moving forward

Since September (2014) I’ve been lucky enough to hold the role as an editor for SitePoint. Specifically their Sass channel. One of the great pleasures of doing this is reading other peoples articles on Sass and learning new things. It’s great.

Recently Hugo (you know him? He writes quite a bit about Sass) wrote an article about using breakpoints and tweakpoints in Sass which I really enjoyed reading and editing.

I’ve wanted to adapt the media query mixin he created to include my own ‘needs’ since and have managed to squeeze some time out of the day to create it.

Mash it up

Essentially it’s a ‘mash-up’ of both mixins. It takes what is the media query I’ve been using for two years as it’s inner workings:

@mixin mq($point, $IE9: false, $query1: min, $query2: width) {
    @if $IE9 == true{
        .lt-ie9 & {
            @content;
        }
    }
    @media (#{$query1}-#{$query2}: $point / $doc-font-size +em) {
        @content;
    }
} 

From Hugo’s new tweakpoints and breakpoints media query it’s using the @if and @else if statements. It’s a little more verbose as a mixin and now requires me to possibly have global variables for breakpoints but it also allows me to have granular, component based tweakpoints as I discussed in a recent article.

My new Sass media query mixin now looks like this:

@mixin sassifaction-mq($point, $query1: min, $query2: width, $ie: false) {
  @if map-has-key($tweakpoints, $point) {
    @if $ie == true{
      .lt-ie9 & {
        @content;
      }
    }
    @media (#{$query1}-#{$query2}: map-get($tweakpoints, $point) / $sassifaction-font-size + 0em) {
      @content;
    }
  } 
  @else if map-has-key($breakpoints, $point) {
    @if $ie == true{
      .lt-ie9 & {
        @content;
      }
    }
    @media (#{$query1}-#{$query2}: map-get($breakpoints, $point) / $sassifaction-font-size + 0em) {
      @content;
    }
  } 
  @else {
    @warn "Could not find the value `#{$point}` in either local ($tweakpoints) or global ($breakpoints) contexts. Media block omitted.";
  } 
}

So here, as per Hugo’s mixin we’re looking for a local $point in $tweakpoints and if there’s not one available from that Sass map the mixin will then look for a global $point in $breakpoints and finally failing silently with a @warn notice if neither are available.

Unlike Hugo’s mixin I’m converting my media to ems still, although pretty much a moot point now as proportional media queries work with both px and em. I’m sticking with declaring them in ems so I know it can work on as many browsers as possible.

The best of both worlds

I’m pretty happy with what I’ve got now. I’ve got the increased option of modularity with components I create and the ability to define what type of media query I’m using (up to a point). I’ve also created it’s own litle Github Repo where I’m trying to work out how to get it working with bower, ruby gems and the forthcoming eyeglass too. A work in progress, that side of the development is, thus far.