in Articles

Media Query Management

Responsive web design is arguably the de facto standard in web design today. One of the major principles of RWD is implementing media queries into designs to make them more flexible and more adaptive to the media that renders them. There are many wonderful examples on the web that showcase the power of media queries and how they can facilitate more adaptive designs. The examples are often only a few lines of code. This is great for learning, but those examples do not scale well in a real world project. It’s not always obvious how to organize and maintain your style sheet that includes lots of media quries. Especially if you are relatively new to the field.

An issue that I feel is not discussed enough is how quickly a style sheet can spiral out of control in a real world project. Using large blocks of media queries for the design’s breakpoints will rapidly bloat your CSS and make it increasingly difficult to navigate. Especially after you’ve left the project for awhile and come back to it later.

The following is a scenario that developers often fall into when honing their responsive web design best practices. Especially when learning how to manage media query statements. I hope this article provides you with some insight and prevents you from some of the pitfalls I have fallen into previously.

When I started developing responsive websites, I tended to start by adding a media query block at the bottom of the style sheet. That block would serve as the dumping ground for all the styles that needed adjustment under a given breakpoint. This was before adapting to the Mobile First approach (which I highly recommend). Before long I would have a massive block of rules with hardly any organization. Like the following:

@media screen and (min-width: 750px) {
    h1 {
        font-size: 48px;
        line-height: 52px;
        padding: 28px 0 0 0;
    }

    h2 {
        font-size: 30px;
        line-height: 36px;
    }

    // Headers
    .topMobile { display: none; }

    .bottomNav { display: none; }

    #topContainer, #bigHeaderContainer, .top, .bigHeader {
        display: block;
    }

    #leftContainer {
        .leadsubtitle { font-size: 20px; }

       .callNumber {
            font-size: 40px;
            line-height: 40px;
        }
    }

    #leftColumn {
        display: block;
    }
    #rightColumn { padding: 0 0.5em 1.875em 0; margin-left: 205px; }

    #preFooter {
        display: block;
    }

    #outsideBorderWrapper, #hpContainerWrapper {
        margin: 5.875em .5em 0;
    }

    #leftContainer #imgContainer { @include border(all, #CCCACB); }

    #fullWidth {
        padding-left: 1em;
    }

...

}

This is bad. Don’t do that. Bad monkey.

You will be fine for awhile. But eventually something in the design will change that causes you to go back through the style sheet and make changes. For example, the designer decides to change the font size for text elements. That change requires updating each breakpoint associated with an h2 element.

No big deal, right? You fire up the search feature in your text editor looking for all instances of “h2”. You start jumping all over the css file, changing font size declarations for the h2 element. You can’t keep track of which lines you’ve already changed and you quickly get lost in your style sheet. This is what I like to call the vicious “find and replace” cycle. You start talking to yourself. “Did I already change that line? What about that one? Where did this come from? I don’t remember writing that.” And your colleagues start IMing each other after over hearing your desperate outbursts. “I think something is wrong with Code Monkey, he is talking to his style sheet again”.

There’s a better way. Try adding media queries next to your declared statements. Here is an example:

h2 { font-size: 1em; } 

@media only screen and (min-width: 37.5em) {
  h2 { font-size: 1.25em; }
}

@media only screen and (min-width: 50em) {
  h2 { font-size: 1.5em; }
} 

You’re screaming, “That’s not DRY! Good lord, man, what have you done?! The horror!” I know, but it will make your life so much easier. And there are a few ways you can make this method more DRY, which I’ll go into detail a little later. Stay with me.

There are some wonderful advantages to this method. Your style sheet will be easier to read and more organized. All styles for a given element are in one place in the stylesheet. No need to search for a declaration in each media query chunk at the bottom of your CSS. It will also save you time and your sanity.

You can keep your code even more organized by using Sass to nest media queries inside rules. Here is an example:

h2 {
  font-size: 1em;

  @media only screen and (min-width: 37.5em) {
    font-size: 1.25em;
  }

  @media only screen and (min-width: 50em) {
    font-size: 1.5em;
  }
}

which will result in the following CSS block:

h2 { font-size: 1em; } 

@media only screen and (min-width: 37.5em) {
  h2  { font-size: 1.25em; }
}

@media only screen and (min-width: 50em) {
  h2 { font-size: 1.5em; }
}

There are some disadvantages to this method. Your style sheet won’t be DRY. There will be multiple repeating media query breakpoints scattered throughout the style sheet. But let’s face it, you’re stylesheet probably isn’t DRY in many places. And that’s OK. We can’t be perfect all the time. Having your media queries next to their relative default rule makes the style sheet more organized.

Another potential issue: If you need to change a global breakpoint, you will need to modify each media query declaration in multiple locations in your stylesheet.

These are efficiency roadblocks, but they can be more streamlined if we take advantage of Sass and it’s inherent awesomeness. We can use Sass variables to handle your breakpoint values!

Here is an example:

$baby-dino: 30em;
$mama-dino: 37.5em;
$daddy-dino: 56.25em;

h2 {
    font-size: 1em;

    @media only screen and (min-width: $mama-dino) {
      font-size: 1.25em;
    }
    @media only screen and (min-width: $daddy-dino) {
      font-size: 1.5em;
    }
  }

Feel free to use a naming scheme for your variables that suits you. This will keep your code more DRY. It will allow you to quickly update breakpoints by simply updating the variable’s value. And you have the freedom to add more as the design dictates.

Some of you might be protesting with something like “That is still not DRY, you have multiple instances of the same code bits all over your style sheet! A fluffy kitten was just murdered because of your negligence! $%#$@”. And I would not disagree with you. We still aren’t as DRY as we could be.

However, I argue that having your style sheet easier to read and more organized outweighs the notion to keep everything strictly DRY. There is a reason DRY is a web design principle and not part of the ten commandments. It’s also easier to read for other developers and designers that may modify the style sheet in the future. They won’t have to hunt around the document to find all the instances where a certain element is adjusted by a media query.

So in conclusion, write your media queries next to their default element style for easier development and organization. And use Sass, if you are comfortable with preprocessors, to nest your media queries. Also use Sass variables to keep track of your breakpoint values.

Happy coding!

Leave a Reply