DRY vs Media Queries – a use case for Mixins

Warning This article was written over six months ago, and may contain outdated information.

CSS pre-processors like Sass and LESS extend CSS in many useful ways, not least by allowing you to use variables in your code either as single values or blocks of multiple property/value pairs, called Mixins. So useful are these that developer Tab Atkins proposed to the W3C that they be adopted into CSS itself, but they were rejected as no suitable use cases were seen.

I think I’ve found a scenario in which, while the use of Mixins aren’t vital, they’re certainly very useful, and it’s because of one of the core principles of coding: DRY (Don’t Repeat Yourself).

Just in case you’re not familiar with Mixins, they are reusable blocks of code. In Sass they’re defined with the @mixin at-rule and a unique identifier, like so:

@mixin foobar {
  color: red;
  font-size: 1.5em;
}

And wherever you want those rules to apply, you call them with @include:

h1 {
  @include foobar;
  font-weight: bold;
}
h2 { @include foobar; }

So you can see, it prevents repetition. The W3C’s case is that you can code around this using CSS as it is:

h1, h2 {
  color: red;
  font-size: 1.5em;
}
h1 { font-weight: bold; }

Which is fair enough in the example I’ve provided, and in simple stylesheets. But what about in more complex stylesheets? Depending on how they’re ordered, you either have to use some selectors very far away from where the other rules are applied to it, or you repeat the rules. And what happens when you bring Media Queries into the equation?

Imagine you have two elements and you want to have them styled differently, but if a media query is in play for them both to be the same, like this:

h1 { color: red; }
h2 { color: blue; }
@media screen and (max-width: 640px) {
  h2 { color: red; }
}

NB: I’ve used only a single property here for the sake of clarity, but it’s more likely I would be using multiple properties so the situation would be even more complicated.

To avoid repeating myself I could add a class to the h1 using JavaScript and matchMedia, but that of course relies on the user having JS enabled and so isn’t a real solution. Or I could pre-process the CSS with a server-side language, but again that’s reliant on another technology which I can’t say for certain is available (in an offline appplication, for example).

With the example I’ve given, I could actually approach the problem from the opposite direction:

h1, h2 { color: red; }
@media screen and (min-width: 640px) {
  h2 { color: blue; }
}

But that means the queries I use are being forced on me by the limitations of CSS; I may want to use my original query for different reasons, but if I want to avoid repetition I have no choice.

That’s where Mixins would come in handy, allowing me both the flexibility to choose the queries that better suit the way I’m working, and avoiding repetition:

@mixin primarycolor { color: red; }
h1 { @include primarycolor; }
h2 { color: blue; }
@media screen and (max-width: 640px) {
  h2 { @include primarycolor; }
}

So, there’s my use case. It’s not bulletproof, there are ways around it, but they all impose limitations on me which I don’t feel should be imposed. I’d be interested to hear your thoughts on this, so please leave a comment if you have something to add.

2 comments on
“DRY vs Media Queries – a use case for Mixins”

  1. s/sass/scss/
    (in your examples you’re actually using scss, not sass).

  2. I do the same thing — actually, I do both; I usually create a mixin and a selector that @includes the mixin. Then I @extend the selector for everything in the global scope, and @include the mixin for everything inside a media query.

    It would really be handy to @extend a globally scoped selector from inside a @media query, but I can understand why it can’t be done (anymore) in SASS — CSS doesn’t allow it either.

    SASS 3.2 now includes ‘placeholder selectors’, which allow you to define selectors that don’t get ouput, but that can be @extended by other selectors. You still can’t @extend them from within a @media query if it’s defined in the global scope, but I think that it would be great if SASS allowed it, and simply kept track of which selectors are being extended where within each scope, and created a bunch of duplicate content automatically. We’re already forced to duplicate content with mixins, so what’d be the harm, I say?

    Paul d'Aoust [October 12th, 2012, 19:06]