Grow your CSS skills. Land your dream job.

Media Queries, Sass 3.2, and CodeKit

Published by Chris Coyier

Media queries are already awesome. Media queries in Sass are already awesome. Media queries in Sass 3.2 are going to be really awesome. This is how you can get CodeKit to start using it.

This isn't a brand new idea. Ben Schwarz did an excellent 7 minute video showing us how it works 7 month ago. Jeff Croft wrote about it 4 months ago. Mason Wendell wrote about it 3 months ago.

The magic is thus

You can already do this in the stable version of Sass (3.1.2):

.column-1-3 {
  width: 33.3333%;
  @media (max-width: 600px) {
    width: 100%;
  }
}

Sass will move it out to valid CSS like this:

.column-1-3 {
  width: 33.3333%;
}
@media (max-width: 600px) {
  .column-1-3 {
    width: 100%;
  }
}

But you might want to do that tons and tons of times in your CSS, because of how awesomely convient and how much sense it makes while authoring (rather than clump them all at the end which breaks cognitive connections).

Now you are stuck repeating yourself a bunch, which is exactly what Sass tries to help us not do. In Sass 3.2 (which is in alpha and has been for a long time) there is a solution. We can write a @mixin which will allow us to "name" media queries.

I:

  1. Like calling media queries "breakpoints"
  2. Don't like the idea of naming them after anything specific, like "iPad"
  3. Like fairy tale analogies

So, I write my mixin like this:

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
}

Now I can write code like:

.page-wrap {
  width: 75%;
  @include breakpoint(papa-bear) { width: 60%; }
  @include breakpoint(mama-bear) { width: 80%; }
  @include breakpoint(baby-bear) { width: 95%; }
}

And it will work just how I want. Cool eh? (Note: that's totally arbitrary code to illustrate the point, usage depends on the project)

But what if you use CodeKit?

CodeKit, rightly, only ships with the stable version of Sass, which doesn't support this yet. I have no idea when Sass 3.2 will go stable. It's been 7 months at least and I was personally anxious to get this going. Thankfully CodeKit recently shipped with a new feature that makes this possible.

As of CodeKit Version 1.2 (6449), you can now tell CodeKit to use an external compiler:

Here's how you get it to work:

  1. Make sure you have at least that version of CodeKit
  2. Open Terminal
  3. Type rvm system. I don't know what this does exactly but CodeKit can't deal with Sass that is installed in rvm directories.
  4. Then install Sass 3.2 with the command sudo gem install sass --pre - you might have to type in your password.
  5. Sass should now be installed at the /usr/bin/ directory
  6. Open CodeKit Preferences and go to Languages and Sass/Scss
  7. Click Choose... under Advanced Compiler Settings
  8. Choose the Sass file in that directory

And done. Note that now you'll be responsible for keeping Sass up to date. But ultimately Sass will go final with 3.2 and CodeKit will update with it and we can go back to using the internal compiler.

Enjoy! It's really quite a pleasure working with media queries this way. Thanks to Christopher Eppstein for helping me with this. Which reminds me, you can do the same exact thing with Compass, just sudo gem install compass and point CodeKit to it as well.

Comments

  1. Brian

    And this is why Sass trumps Less. Nuff said.

    • Sam.web.dev();

      Agreed. I still use LESS (and intend to do so until the new SASS release) because it has a better tutorial and website. Then I will switch, but I still hope that SASS will get a better website/tutorial.

    • Harry
      Permalink to comment#

      I agree with Sam. SASS documentation is not as developed as LESS, making the learning curve more difficult. Until then, it will remain second banana to LESS.

  2. I wanted to use Zurb’s new needs-3.2-SASS version of Foundation, but I also had to update Compass in CodeKit the same way I did SASS before those new media queries would work.

    Hope that helps someone else doing the same thing with Foundation, SASS 3.2, Compass and CodeKit.

  3. Matthew Sullivan

    Less added @media bubbling in 1.3, works the same, same syntax. https://github.com/cloudhead/less.js/blob/master/CHANGELOG

  4. FYI: Less does this too. I’ve been using it for months using CodeKit. It’s really handy, especially when you make the breakpoints a variable that you can remember easily.

    The problem with this technique is that you end up with a CSS file that has dozens and dozens of media query breakpoints being repeated over and over again. Too many of those and rendering slows down.

    I’m waiting for a compiler to, well, compile all the different media query breakpoints into one statement. Not sure if that will ever happen.

    • The problem with consolidating the media queries is that it changes the order of your declarations, and you might end up overwriting your styles, since they’re in the wrong order.

      It’s bad enough when it occasionally happens when @extending. This’ll aggravate the problem to a whole new level.

    • I wrote some code that you can run after compiling to CSS that solves this issue. You can find the repo on GitHub. I am still ironing out the process of ensure all breakpoints are applied in the correct order, but it may be of some use to you. I have this setup to run automatically after compilation with Live Reload.

    • Gabriel Tadeu
      Permalink to comment#

      Using these examples by Jeremy Worboys it’s possible in {LESS} with:

      
      .selector-1 { color: blue; }
      @media screen and (min-width: 40em) {
          .selector-1 { color: red; }
      }
      
      .selector-2 { color: blue; }
      @media screen and (min-width: 25em) {
          .selector-2 { color: green; }
      }
      @media screen and (min-width: 40em) {
          .selector-2 { color: red; }
      }
      

      Do this: (puts both media queries in the end of .css compiled)

      
      .selector-1 { color: blue; }
      
      
      .selector-2 { color: blue; }
      
      
      @media screen and (min-width: 40em) {
      .selector-1 { color: red; }
      .selector-2 { color: red; }
      }
      @media screen and (min-width: 25em) {
      .selector-2 { color: green; }
      }
      

      Because when I try using {LESS} compiler this is the final code:

      
      .selector-1 {
        color: blue;
      }
      @media screen and (min-width: 40em) {
        .selector-1 {
          color: red;
        }
      }
      .selector-2 {
        color: blue;
      }
      @media screen and (min-width: 25em) {
        .selector-2 {
          color: green;
        }
      }
      @media screen and (min-width: 40em) {
        .selector-2 {
          color: red;
        }
      }
      

      They duplicate min-width 40em.

  5. Awesome stuff. I am just starting to touch SASS and really enjoy seeing things like this. Thank you Chris and I can’t wait for the kickstarter screencasts to start rolling.

  6. Anahkiasen

    Try this by the great Eric Meyer : http://susy.oddbird.net/
    You’ll thank me later.

    • I find with responsive designs especially, grids really tend to limit what you can do, and your freedom. Plus, creating your own basic grid with mixins for different size screens via Sass makes it even easier!

    • I tend to agree with Terence on this one – Susy looks like a fantastic system if you’re looking for a responsive grid… but I think forgoing the grid altogether can offer you some seriously creative solutions to expanding the content as the width of your page enlarges.

  7. Yurika

    This article inspires me to use SASS. I can’t appreciate SASS for the long time. But after reading this article, I now consider SASS. I never expect what SASS can do. Thanks for this post!

    -ikay

  8. Denis

    Great inputs.. I will consider this myself.

  9. I’m just starting the journey into Sass, Compass & Susy after using Less for a bit. Like others I can see the power of Sass. Awesome features. Hope it’s worth the it!

  10. Any readers of .net magazine might like to know that I covered Sass 3.2 media queries too a few months back (with input from the venerable Mr Eppstein). Due to publication times (print runs etc) it’s just come out in the current print issue. It’s the one promoted on the netmagazine.com site at present. Also, Sass 3.2 can also play happily with LiveReload (beta 3.16 I think?).

    One thing is certain: once you’ve done a few responsive sites with 3.2 media querie mixins, you’ll never go back.

  11. In SCSS you can also setup your breakpoints like this:

    $mamabear: 25em;
    
    $papabear: 40em;
    
    $goldenbear: 70em;

    And then…

    .l-site-container {
    padding: 0 5%;
    
    @media (min-width: $mamabear){
    padding: 0 10%;
    }
    
    @media (min-width: $papabear){
    width: 90%;
    }
    
    }

    Slightly simpler? Probably doesn't make a difference... unless someone can point one out?

    I've been doing this for a while now and it seems to do the job.

    Though I am eagerly awaiting the ability to compile all elements etc under one breakpoint variable into a single part of the final CSS sheet.

    • That’s cool, but what if your media queries are more complicated?

      @media only screen 
      and (min-device-width : 768px) 
      and (max-device-width : 1024px) 
      and (orientation : portrait)
      and (-webkit-min-device-pixel-ratio : 1.5) {
      
      }

      Just a variable isn’t going to cut it at the point, it’s best to have the whole media query as a variable. I guess tutorials like mine above should make the point stronger with examples like this.

    • Yep – that’s pretty much the feedback I was looking for. Good point.

  12. Chris, the answer to “what if your media queries are more complicated” is Breakpoint:

    http://github.com/canarymason/breakpoint

    Compass extension for uber easy media queries, basically the variable approach as pointed out, but with the power to have super complex media queries. Check it out.

    • Interesting. I recently went to a presentation about another Breakpoint library — https://github.com/lesjames/breakpoint.

      It may be similar to the breakpoint approach you mentioned, but it has the advantage of being grid based — so instead of figuring out your widths and using variables, you just determine how many columns you’re expecting for a specific layout, and it does the math for you. For example:

      
      // 8 column breakpoint
      @include breakpoint(8){
          .fluid-demo {
              .grid-cell { width: fluid(4); }
          }
          .fixed-demo {
              .grid-cell { width: fixed(2); }
          }
      }
      
      // 12 column breakpoint
      @include breakpoint(12){
          .fluid-demo {
              .grid-cell { width: fluid(3); }
          }
          .fixed-demo {
              .grid-cell { width: fixed(3); }
          }
      }
      

      I haven’t tried it out (don’t have SASS 3.2, on Windows) but the author’s demo was pretty awesome.

  13. I’m trying to integrate this technique (thanks Chris, it’s awesome!) but I’m having a hard time with the retina target media querie.

    @mixin breakpoint($point) {
      @if $point == 2x {
        @media only screen and (-webkit-min-device-pixel-ratio: 1.5),
        @media only screen and (min--moz-device-pixel-ratio: 1.5),
        @media only screen and (min-device-pixel-ratio: 1.5) { @content;  }
        }
    }</code

    This does not compile. If someone has any idea. Or if it's even possible to do with sass.

    • Nevermind, I finally fixed it:

      
      @mixin breakpoint($point) {
      	@if $point == 2x {
      		@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
      		only screen and (min-moz-device-pixel-ratio: 1.5),
      		only screen and (min-device-pixel-ratio: 1.5) { @content; }
      	}
      }
      
  14. So doing this outputs multiple @media queries for each selector. Have you done and performance tests to see if having multiple media queries for the same breakpoint is better than a single media query for each?

    For instance:

    .container {
        width:1140px;
        @media (min-width:320px) {
            width: 100%;
        }
    }
    
    .heading {
        font-size:24px;
        @media (min-width:320px) {
           font-size:20px;
        }
    }
    /* Formats  into */
    .container { width:1140px; }
    @media (min-width:320px) {width: 100%; }
    
    .heading {  font-size:24px; }
    @media (min-width:320px) { font-size:20px; }
    

    If you have that for EACH selector in your CSS wouldn’t that put a damper on your performance? I assumed 1 media query per breakpoint was the De facto standard for a reason.

    • I guess I kind of missed Jeremy’s post about his Sassy Media compiler. Looks great! If he could build that into a Sublime Text plugin that would be super awesome!

    • Hi Brian, I have opened a new issue on GitHub for a Sublime Text 2 plugin. I would appreciate your thoughts on how you would like to interact with the plugin.

    • Very much looking forward to this sublime text plugin (assuming someone else knows how to implement it).

    • Hi David, I will be writing the plugin. If you head over to the issue GitHub you will see the discussion Brian and I had regarding how you would run it. Feel free to add your own opinion to the mix.

  15. “Which reminds me, you can do the same exact thing with Compass, just sudo gem install compass and point CodeKit to it as well.”

    THIS JUST SAVED MY LIFE.
    I could never get Compass plugins to work. The entire Compass plugin world just opened up again. WOOOO.
    Codekit + Adobe Shadow + Dev Tools + Sublime Text.
    The tools are just amazing these days.

    • Emyr Thomas
      Permalink to comment#

      Jeff, the set of tools you mention really are amazing, I agree. I know of Codekit, Adobe Shadow and Sublime Text, but what is Dev Tools?

    • Emyr Thomas
      Permalink to comment#

      I assume you mean the WebKit Dev Tools right?

  16. Jhon
    Permalink to comment#

    Can this be applied to the mobile first approach, I mean that the media queries are placed in a special css file only for capable media queries browser at the same time creating an ie fixed witdth? If anything I said makes anysense.

  17. By the way, if you’re using Foundation 3, you’ll need the 0.13.alpha.x version of Compass if you want to Pointe CodeKit to an external Compass compiler. When Compass officially releases this version, and CodeKit includes this compiler, you can just use CodeKit’s compiler.

    Do a sudo gem install compass --pre to get the bleeding edge.

    And for me, Sass and Compass were not installed to the /usr/bin directory, but instead to the /Library/Ruby/Gems/1.8/gems/[sass/compass version]/bin directory

  18. Joel
    Permalink to comment#

    I followed the above instructions to get Sass 3.2 working in Codekit (thanks Chris), which seemed to go well … except that I don’t think Codekit is really using Sass 3.2. The placeholder selector feature does not work, ie: %classname can not be @extend(ed).

    Codekit seemed to take the new Sass path and shows that it is using /usr/bin/sass which, when tested with sass –version is indeed 3.2.0.alpha.277.

    Can anyone guess what I might be doing wrong? Thanks in advance!

  19. Joel
    Permalink to comment#

    To make a permanent record of my stupidity: I did @extend .placeholder rather than @extend %placeholder. Updating Sass and Compass actually worked.

  20. Travis
    Permalink to comment#

    Instead of breakpoints, im calling it respond-to and there is a default option and a tablet option

    Doesn’t work for me… I get the following error

    Invalid CSS After “…ond-to(tablet) ” : expected “}”, was “{width:60%;}”

    Heres mine:

    
      @mixin respond-to($media) {
      @if $media == default {
        @media (min-width: 1024px) { @content; }
      }
     
      @else if $media == tablet {
        @media (max-width: 1024px) { @content; }
      }
    }
    

    And further down I call it here

    
    .class
    {
         width:100%;
    
        @include respond-to(table) { width:60% }
    }
    
  21. Travis
    Permalink to comment#

    er, respond-to(tablet)

    Its spelt right in my css, i just spelled it wrong in the comment

  22. Travis
    Permalink to comment#

    Got it. I was on SASS 3.1 and needed to upgrade in order for it to work.

  23. Is there a way to clump all those breackpoints into one really big section in the CSS when compiled? I mean, is there a way that you can set the location in your stylesheet to paste all of those together, like say… a “Responsive” section? Also, is there a way to compile them to fit under a single query if there are multiple classes using the same breackpoint?

  24. Permalink to comment#

    $small:480;
    $med:720;
    $large:1280;

    @mixin breakpoint($point, $dir: min) {
    @media (#{$dir}-width: $point) {
    @content;
    }
    }

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".