Last Updated: February 25, 2016
·
1.322K
· artinruins

The End-all SASS Media Query Mixin

The code explains itself, so, here it is:

$mq-support: true !default;
@mixin pe-media( $min: null, $max: null,  $height: false, $serve-to-nomq: true ) {

    @if $min == null and $max == null  {
        @warn "Mixin PE-Media requires at least a MIN or MAX width/height";
    }

    $direction: 'width'; 
    /* If $height is true, override the variable. */
    @if $height == true {
        $direction: 'height'; 
    }

    @if $mq-support {
        @if $min != null and $max != null {
            @media ( 'min-' + $direction + ':' + $min ) and ( 'max-' + $direction + ':' + $max ) {
                @content;
            }
        } @else if $max != null {
           @media ( 'max-' + $direction + ':' + $max ) {
                @content;
            }
        } @else {
            @media ( 'min-' + $direction + ':' + $min ) {
                @content;
            }
        }
    } @else {
        @if $serve-to-nomq {
            @content;
        }
    }
}

@include pe-media() accepts the following arguments:

$min: null
Required. Will be used as @media ( 'min-' + $direction + ':' + $min )

$max: null
Optional. Will add and ( 'max-' + $direction + ':' + $max )

$height: false
Optional. If set to true, the internal variable $direction will be set to height, changing the min/max queries to height instead of width.

$serve-to-nomq: true
Optional. A way to tell the function not to output ANYTHING to non-media-query enabled browsers.

Now, let's explain it a bit.

Say you have this markup:

<div class=”col-row default-columns”>
    <article class=”column main-content” role=”main”>
        Content
    </article>
    <aside class=”column main-sidebar” role=”complementary”>
        Content
    </aside>
</div>

With this SCSS and our magical pe-media() mixin:

.default-columns {

    @include pe-media( $breakpoint-small, $serve-to-nomq: false ) {

        & > [role="main"], & > [role="complementary"] { float: left; }

        & > [role="main"] { width: 60%; }

        & > [role="complementary"] { width: 40%; }
    }

    @include pe-media( $breakpoint-medium ) {

        & > [role="main"], & > [role="complementary"] { float: left; }

        & > [role="main"] { width: 67%; }

        & > [role="complementary"] { width: 33%; }
    }
}

We will get this CSS for media-query enabled browsers:

@media (min-width: 600px) {
    .default-columns>[role="main"],.default-columns>[role="complementary"] {
        float:left;
    }
    .default-columns>[role="main"] {
        width:60%;
    }
    .default-columns>[role="complementary"] {
        width:40%;
    }
}

@media (min-width: 740px) {
    .default-columns>[role="main"],.default-columns>[role="complementary"] {
        float:left;
    }
    .default-columns>[role="main"] {
        width:67%;
    }
    .default-columns>[role="complementary"] {
        width:33%;
    }
}

And this CSS for non-media-query enabled browsers:

.default-columns>[role="main"],.default-columns>[role="complementary"] {
    float:left;
}
.default-columns>[role="main"] {
    width:67%;
}
.default-columns>[role="complementary"] {
    width:33%;
}

Our SASS files are set up with one master _project.scss file that includes a bunch of partials for our functions, mixins, variables, etc… and contains all of our site styles inside and outside of this mixin. Then we have two files that compile to CSS: mq.scss and no-mq.css.

mq.scss=

@import "project";

That’s it. Since we set $mq-support to true right before the mixin, everything inside project is ready to be compiled. For no-mq.scss, there is only one slight change:

no-mq.scss=

$mq-support: false;
@import "project";

Since that variable has been changed in this instance, everything using our mixin inside project will be parsed differently.

Why? Because it is awesome.

Because of this mixin and the way t works, we can apply @media queries inline per element instead of grouping them all together in one place or another. So while you are writing styles for <header> and all the element it contains, you can easily write additional styles wrapped in breakpoints to quickly see what elements in your header do at different sizes.

You can use variables to define your major breakpoints, or you can throw in specific breakpoint values for the element you are working with. As Ben Callahan stated, "There is no breakpoint". This method keeps all your styles across different breakpoints in one place, and gives you control over which styles get compiled for older browsers.

1 Response
Add your response

If someone can tell me how to escape @else in code blocks, I can go in there and fix them so we don't get <a href="/else">@else</a> instead. Thanks.

over 1 year ago ·