{"id":235042,"date":"2015-11-23T04:00:14","date_gmt":"2015-11-23T11:00:14","guid":{"rendered":"http:\/\/css-tricks.com\/?p=235042"},"modified":"2016-07-13T09:31:25","modified_gmt":"2016-07-13T16:31:25","slug":"keeping-breakpoints-dry","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/keeping-breakpoints-dry\/","title":{"rendered":"On Keeping Breakpoints DRY"},"content":{"rendered":"

The following is a guest post by Eduardo Bou\u00e7as<\/a>. Eduardo is back to follow up on his journey of approaching media queries programatically. He’ll catch you up on how this started, where it’s went, and how that’s going.<\/em><\/p>\n

<\/p>\n

A year ago, I went on a personal quest<\/a> to find the best way to use the powers of CSS preprocessors to manage breakpoints and write media queries in my projects. The outcome was include-media<\/a>, a library that promises “simple, elegant and maintainable” media queries in Sass. But how did that work out for me?<\/p>\n

The first two adjectives above are actually quite subjective, since simplicity and elegance eventually boil down to personal preference — there’s no point in talking about those. Instead, I’d like to share with you my personal experience of using the library for a year on commercial projects, and how it particularly helped me with the third aspect: maintainability.<\/p>\n

Back to the basics<\/h3>\n

The need for something like include-media comes from a problem that developers absolutely hate: repeating code. Until element queries<\/a> become a thing and we start thinking of responsive design at a component level, we’re stuck with media queries that respond to changes in the global viewport, not in the context of the element.<\/p>\n

As a result, developers often define “global breakpoints”, which are really just arbitrary viewport sizes at which elements in a page may change form. Even though that’s a simple concept that can be easily implemented in vanilla CSS, there’s an immediate advantage that a pre-processor can bring to the table: the ability to define these breakpoints dynamically as variables, allowing developers to declare them just once and reference them everywhere.<\/p>\n

$breakpoints: (\r\n  'small': 400px,\r\n  'medium': 900px,\r\n  'large': 1200px\r\n);<\/code><\/pre>\n

Over the last year, I’ve been focusing on taking that principle even further, by making these breakpoint declarations available in different contexts.<\/p>\n

Enter JavaScript<\/h3>\n

It’s not uncommon to reference the window width within a JavaScript routine. For example, you might be executing a piece of code that changes the behaviour of a certain element in the page, but that element might only be displayed on large viewports anyway. In that case, it could be sensible to skip the execution completely if the window is smaller than a certain value.<\/p>\n

.foo {\r\n  display: none;\r\n\r\n  \/\/ We're referencing the name of\r\n  \/\/ the breakpoint, not the actual value\r\n  @include media('>=large') {\r\n    display: block;\r\n  }\r\n}<\/code><\/pre>\n
function doStuff() {\r\n  \/\/ Bollocks, we're still referencing the value here!\r\n  if (window.innerWidth < 1200) {\r\n    return;\r\n  }\r\n    \r\n  doHeavyStuff();\r\n}<\/code><\/pre>\n

But there we are again — that “certain value” is one of the breakpoints we so proudly defined just once in our style sheets, but we’re now redeclaring its value since the name large<\/code> won’t mean anything in JavaScript. So much for keeping things DRY.<\/p>\n

To get around that, there’s a plugin called include-media-export<\/a>, a combination of a SCSS routine that writes information about the breakpoints to the DOM, and a small JavaScript utility to read and process it. With the plugin, I can rewrite the function above without redeclaring the breakpoint, so all is good if someone decides to change its value down the line.<\/p>\n

function doStuff() {\r\n  \/\/ Yay, we're DRY again!\r\n  if (im.lessThan('large')) {\r\n    return;\r\n  }\r\n    \r\n  doHeavyStuff();\r\n}<\/code><\/pre>\n

The im<\/code> object exposes the name of the current active breakpoint through im.getActive<\/code>, while im.greaterThan<\/code> and im.lessThan<\/code> determine whether the window is wider or narrower than a certain breakpoint.<\/p>\n

This is not a new concept, and many others wrote about it in the past (namely Les James<\/a> and Mike Herchel<\/a>). The idea here is to tie everything together in the same ecosystem, making the experience seamless for the developer. <\/p>\n

There’s also layout<\/h3>\n

I don’t use any grid systems per se, but I find it convenient to have some classes purely for layout purposes. When applied to an element, these classes will define its width, instead of manually setting it on individual selectors \u2014 this keeps the style sheet organised and makes the markup a bit more semantic. <\/p>\n

I used to end up with something like this:<\/p>\n

.col--1-2 {\r\n  width: 50%;\r\n}\r\n\r\n.col--1-3 {\r\n  width: 33.3333%;\r\n}\r\n\r\n.col--2-3- { \/* etc. *\/ }<\/code><\/pre>\n

After reading Harry Robert’s piece about BEMIT<\/a>, I became really interested in his responsive suffixes<\/em> approach. He suggests including a class with the name of a breakpoint to describe the state of an element at that screen size (e.g. .class-name@breakpoint<\/code>). That idea led to include-media-columns<\/a>, a plugin that generates column classes based on the breakpoints defined in include-media, following BEMIT’s naming convention.<\/p>\n

Let’s take the list of breakpoints we defined before and imagine a user profile component that must:<\/p>\n