Modular CSS with Media Queries and Sass

How to get best performance from CSS Sass MediaQueries

by Janeth Kent Date: 23-08-2019 css sass mediaqueries webdesign

Most developers nowadays are recognizing that if you’re developing large applications that have different views and states, it is best to take a modular or object-oriented approach to your CSS development.

When you throw media queries into the mix, however, the you can lose some of the benefits of modularity — code that’s easy to read, update, and maintain.

Let’s look at different ways we can write our media queries, starting with what might be the most common approach — especially with those not yet using a preprocessor.

The Common Approach

To demonstrate what I think the majority of developers have done with media queries up to this point, here’s a simple example:

.box-module {  
  float: left;  
  background:  #ccc ;  
  margin-bottom: 1.2em;  
}  
  
.some-other-module {  
  border: solid 4px #222;  
  padding: 1.2em;  
  margin-bottom: 1.2em;  
}  
  
/* ... other non-media query styles would go here ... */  
  
@media screen and (max-width: 720px) {  
  .box-module {  
    float: none;  
    clear: both;  
    margin-bottom: .5em;  
  }  
  
  .some-other-module {  
    border: solid 2px #222;  
    padding: .8em;  
    margin-bottom: .5em;  
  }  
}  
  
@media screen and (max-width: 320px) {  
  .box-module {  
    margin-bottom: .2em;  
  }  
  
  .some-other-module {  
    padding: .2em;  
    margin-bottom: .2em;  
  }  
}  
  
/* ... other media query styles would go here ... */  

In the first two rule sets in this example, we have two separate elements on the page styled without media queries. (As a side point, those first two rule sets could be our mobile first styles, but it really doesn’t matter for the purpose of this theoretical example.)

After we declare those primary styles on our two elements, we then declare our media queries, repeating the same selectors, but with altered styles to suit the media features defined in the media queries.

The key part to take note of here is how this would look if we had thousands of lines of code. If that were the case, the media query styles that apply to the same modules would be significantly separated from the original styles for those same elements. Not ideal, especially when you’re trying to keep related chunks of CSS together.

A More Modular Approach

The purpose of modularizing our CSS is to help it become much more flexible and scalable, but also to help make it easier to read and easier to maintain. As we can see from the previous example, that approach (where you throw all your media queries at the bottom of the stylesheet) can, to some extent, hinder maintainability.

Let’s rewrite the example from above using a more modular approach:

.box-module {  
  float: left;  
  background:  #ccc ;  
  margin-bottom: 1.2em;  
}  
  
@media screen and (max-width: 720px) {  
  .box-module {  
    float: none;  
    clear: both;  
    margin-bottom: .5em;  
  }  
}  
  
@media screen and (max-width: 320px) {  
  .box-module {  
    margin-bottom: .2em;  
  }  
}  
  
.some-other-module {  
  border: solid 4px #222;  
  padding: 1.2em;  
  margin-bottom: 1.2em;  
}  
  
@media screen and (max-width: 720px) {  
  .some-other-module {  
    border: solid 2px #222;  
    padding: .8em;  
    margin-bottom: .5em;  
  }  
}  
  
@media screen and (max-width: 320px) {  
  .some-other-module {  
    padding: .2em;  
    margin-bottom: .2em;  
  }  
}  

This might seem a bit odd and counterproductive to those who are accustomed to putting their media queries at the bottom of their CSS file. This approach is discussed as an option in Jonathan Snook’s book on modular CSS, where he discusses changing state with media queries.

Even before I started reading Jonathan’s book, I’ve considered this approach, but pretty much immediately discarded the thought for probably the same reason that many of you are cringing at it right now: The fact that this clearly goes against the DRY (Don’t Repeat Yourself) principle.

Pros and Cons

As we’ll see in the following sections, if you’re using Sass, the repetition becomes less of a factor and, from what I can tell, many developers are adopting this method.

But first, let’s consider the pros and cons of this approach for pure CSS that’s not using Sass.

Cons:

    Lots of repetition, which modular CSS discourages More code, which could amount to hundreds of extra lines, thus larger files Could be confusing to future maintainers, especially if not well documented If you change a single media query state (e.g. “max-width: 720px”), you have to change it for all modules

Pros:

    Easier to read/understand/maintain for the original developer(s) Could be much easier to read/understand for future maintainers, especially if well documented Easier to write the initial code (more on this below)

Resolving Some of the Cons

To purists, the cons may seem like big problems. But I don’t think they’re as big as they seem, even though they may appear to outweigh the pros.

First, I’m not concerned about the larger amount of code. If I’m minifying and gzip’ing, the difference in code quantity will be negligible.

Second, as suggested by the final “pro” point, if you’re writing your media query for a module right next to the initial styles for the module itself, I believe this will make it significantly easier when debugging that particular part of the code. Since you have all the different styles for a particular module together — including all the different state changes via media queries — you’ll quickly be able to make any changes and won’t have to put off debugging the same module again at smaller breakpoints.

Modular Media Queries with Sass

When you factor in a preprocessor like Sass, this sort of thing becomes exponentially easier. If you’re not familiar with some of Sass’s media query-specific capabilities, it’s worth checking out that part of their documentation, which talks about doing this exact thing.

So let’s rewrite our example from above using Sass with nesting and variables:

$media: screen;  
$feature: max-width;  
$value: 720px;  
$value2: 320px;  
  
.box-module {  
  float: left;  
  background:  #ccc ;  
  margin-bottom: 1.2em;  
  
@media #{$media} and ($feature: $value) {
    float: none;  
    clear: both;  
    margin-bottom: .5em;  
  }  
  
@media #{$media} and ($feature: $value2) {
    margin-bottom: .2em;  
  }  
  
}  
  
.some-other-module {  
  border: solid 4px #222;  
  padding: 1.2em;  
  margin-bottom: 1.2em;  
  
@media #{$media} and ($feature: $value) {
    border: solid 2px #222;  
    padding: .8em;  
    margin-bottom: .5em;  
  }  
  
@media #{$media} and ($feature: $value2) {
    padding: .2em;  
    margin-bottom: .2em;  
  }  
  
}  

Here, in addition to variables, we’re using Sass’s nesting capabilities, which don’t require repeating the selector inside the media query block. This will compile to basically what we did in the Sass-less modular example above.

But we’re not finished yet. Let’s make one final improvement to this code, using a fairly new Sass feature.

Modular Media Queries Using Sass with @content

We’re going to improve on this even more by using Sass’s ability to pass content blocks to a mixin.

And I should point out that this is nothing new; the official Sass blog discussed this shortly before Sass 3.2 was released, and a few other blogs have discussed the benefits of using Sass to keep media query styles near the styles they override.

Here’s our updated code using Sass’s @content directive:

$media: screen;  
$feature: max-width;  
$value: 720px;  
$value2: 320px;  
  
@mixin modular-mq($breakpoint) {
@if $breakpoint == medium {  
@media (#{$media} and $feature: $value) { @ content; }  
  }  
@else if $breakpoint == small {  
@media (#{$media} and $feature: $value2) { @ content; }  
  }  
}  
  
.box-module {  
  float: left;  
  background:  #ccc ;  
  margin-bottom: 1.2em;  
  
@include modular-mq( medium) {  
    float: none;  
    clear: both;  
    margin-bottom: .5em;  
  }  
  
@include modular-mq( small) {  
    margin-bottom: .2em;  
  }  
  
}  
  
.some-other-module {  
  border: solid 4px #222;  
  padding: 1.2em;  
  margin-bottom: 1.2em;  
  
@include modular-mq( medium) {  
    border: solid 2px #222;  
    padding: .8em;  
    margin-bottom: .5em;  
  }  
   
@include modular-mq( small) {  
    padding: .2em;  
    margin-bottom: .2em;  
  }  
}  

The examples with the variables and whatnot are not necessarily going to be done like that. You can hardcode the values right into the mixin, or you could have some conditional logic that decides what the values will be. This is more or less a theoretical example.

Conclusion

Even with the two Sass examples, you’re still, to some extent, repeating your media query breakpoints for every selector that needs an override. So I can understand if many developers don’t like this approach.

Overall, I think the concept of keeping related styles near each other is much more in line with what we like to see in CSS and especially in modular or OOCSS. I always find it annoying when I have to sift through two different parts of a stylesheet to make a change to a single element on the page — a problem that has occurred much more often with the advent of media queries. I think this approach would resolve this type of thing.

I should also mention that there are some projects that aim to help in this area including Sassy Media, Susy, sass-mediaqueries and probably others that I haven’t yet seen. (Update: Scott Kellum tweeted to me about Breakpoint, which is worth checking out just for the Point Breakmovie homage.)

So how has everyone been doing this sort of thing? Do you mind having your media queries scattered throughout your code, repeating the same queries for different selectors?

 
by Janeth Kent Date: 23-08-2019 css sass mediaqueries webdesign hits : 4996  
 
Janeth Kent

Janeth Kent

Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN AND DEVELOPMENT.

 
 
 

Related Posts

New graphic window units - CSS

''Intercop 2022' is a project announced by Google, Microsoft, Apple and the Mozzilla Foundation to make all browsers offer the same web experience. The project has 15 focus areas and one…

Let's create a Color Picker from scratch with HTML5 Canvas, Javascript and CSS3

HTML5 Canvas is a technology that allows developers to generate real-time graphics and animations using JavaScript. It provides a blank canvas on which graphical elements, such as lines, shapes, images…

Why shouldn't we use black?

Nowadays it is becoming more and more common for web pages to have the option to set them in dark mode, or to base their aesthetics directly on black or…

How to make your own custom cursor for your website

When I started browsing different and original websites to learn from them, one of the first things that caught my attention was that some of them had their own cursors,…

Nesting: future proofing CSS

Although not currently supported by browsers, there is a proposal for CSS nesting to support a feature that would provide better readability to native CSS, so in the future it…

Use the SRCSET attribute to improve your SEO

There is a new standard HTML attribute that can be used in conjunction with IMG called SRCSET. It is new and important as it allows webmasters to display different images…

Starting with Bootstrap-Vue step by step

Today we will show you how to use BootstrapVue, describe the installation process and show basic functionality. The project’s based on the world's most popular CSS framework - Bootstrap, for building…

Bootstrap 5 beta2. What offers?

Since the release of the Bootstrap 4 is three years, in this article we will present what is new in the world’s most popular framework for building responsive, mobile-first sites.…

Creating simple CSS spinner-loader

In today's article we will show you how to animate a basic loader that spins when some predefined action is defined, such as loading an image. That can be used…

How to use Parallax.js effect on your website

Today, we're going to write about the parallax effect, similar to parallax scrolling, and how to implement it to improve your landing page. In webdev, they say mobile first -…

How to make the website's dark mode persistent with Local Storage, CSS and JS

Recently we wrote about how to do a switchable alternative color mode or theme, a very useful and popular feature to websites. Today’s article is going to be about how…

The easiest way to align items using flexbox

With the release of flexbox in CSS, it has become an essential tool when placing elements next to each other, since, by default, the children of a display: flexare stacked…

Clicky