🚀 See the 2024 Ruby on Rails Community Survey results!
Article  |  Development

The Pros and Cons of Modular Sass

Reading time: ~ 6 minutes

Using modular Sass

In the past year or so, the front-end developers at Planet Argon have taken more of a modular approach to writing CSS. This means writing CSS in a way that promotes forward-thinking, scalability, and ease of development. Before I get into the pros and cons, here’s a quick example of the difference between a modular and non-modular approach.

Non-modular

div.author-block {
  background-color: rgba(255,255,255,.3);
  float: left;
  padding: 5%;
  width: 50%;
  img {
    background-color: #FFF;
    border: 1px solid rgba(0,0,0,.3);
    float: left;
    padding: 2%;
    width: 30%;
  }
}

Modular

.bordered {
  background-color: #FFF;
  border: 1px solid rgba(0,0,0,.3);
  padding: 2%;
}
.media {
  background-color: rgba(255,255,255,.3);
  float: left;
  padding: 5%;
  width: 50%;
}
.media-image {
  @extend .bordered;
  float: left;
  width: 30%;
}

Let’s dive into the non-modular approach first. The addition of the ‘div’ qualifier to the ‘author-block’ selector reduces the modularity of that rule – it’ll only work if the element happens to be a div. What if I wanted to style a paragraph or article element in the same way? Also, nesting the ‘img’ tag selector (this is Sass, if you hadn’t noticed – specifically the SCSS syntax), which results in the CSS output ‘div.author-block img’, is quite specific. Not only does that particular element need to be an image, it needs to be within the ‘author-block’ div.

We can see that the modular approach looks a bit different. We renamed ‘author-block’ to the more generic ‘media’ because I imagine that we might want to reuse this very common pattern (container with image floated left) and the author might not always be the star of the show. I also created a helper class called ‘bordered’ which adds some padding and a border to an element. The class can now be used on its own or extended, as in the case of the ‘media-image’ rule.

Embrace Bootstrap

Admittedly, I don’t love everything about Bootstrap. It’s great for making sites with that familiar Bootstrap look, which isn’t always the desired aesthetic. But Bootstrap has served as a handy introduction to modular front-end code. We started taking advantage of Bootstrap’s utility classes, like “text-right”, “pull-right” and “muted,” and shortly thereafter began creating our own.

In my opinion, the good far outweighs the bad. I find great satisfaction in marking up a page, styling it appropriately with helper/utility classes, and writing as little custom CSS as possible. The best is creating entire sections without touching the CSS. This is indicative of two things: I’ve decreased development time, and I reinforced a pattern or patterns. Designs often have slight inconsistencies (a 12px font here and a 13px font there, or a 10px padding here and 11px padding there). Don’t tell the designers, but I consider it part of my job to iron out these unintentional incongruities. Creating and sticking to CSS patterns (or modules) is a great way achieve this.

Pros of Modular Sass

Development time

Once the modules/patterns are in place, coding your site can be almost as quick as writing HTML. The more modular your patterns and helpful your utility classes, the less custom CSS you need to write. Coming up with a clever class name and writing ‘font-size: 16px;’ 60 times in your CSS is way more time-consuming than leveraging a style that already exists (for font sizes, I really like Bootstrap’s model of headline helper classes – use the ‘h1’ class to style text like an <h1>, or the ‘h3’ class to style text like an <h3>).

Consistency

Again, once we’ve created the modules, it is much easier to reuse our patterns than to create new pieces. This means that, moving forward, our site will remain consistent regardless of the scale.

Stylesheet organization

Since we’re using Sass, we can take advantage of the @import directive, which allows us to break our CSS into multiple partials for organizational purposes. We can have one partial for our reset, one for typography, one for grids, etc. The advantage of this approach over the native CSS @import rule is that our Sass partials can be compiled into one stylesheet, eliminating the need for all those extra HTTP requests.

Cons of Modular Sass

Initial time investment

In a way, diving into writing CSS with no thought about scalability or reusability, even at the expense of having to reinvent the wheel a bit, can begin quite quickly. Building modules requires both an awareness of the project as a whole and a willingness to invest time and energy into thinking about and planning for the future of the project.

Extra classes in the markup – a semantic or performance faux pas?

One might frown on 3 or 4 or even 5 classes attached to a particular HTML node; fortunately, there are ways around this. Since we’re writing Sass, we can utilize the @extend directive and placeholders to eliminate the need for extra classes in the markup. A placeholder selector, represented by % sign, only appears in the output CSS where it’s been extended. Here’s an example of what this might look like:

Sass

%bordered {
  border: 1px solid #CCC;
}
%pull-right {
  float: right;
}
.padded {
  padding: 10px;
}
.fancy-box {
  @extend %bordered;
  @extend %pull-right;
  @extend .padded;
}

CSS output

.padded {
  padding: 10px;
}
.fancy-box {
  border: 1px solid #CCC;
  float: right;
  padding: 10px;
}

Using this method, we can reduce both the amount of CSS (thanks to placeholder selectors) and classes we reference in our markup. Personally, I don’t end up using many placeholders in my CSS – I find it more advantageous to use classes for these utilities so that I can reference them in the HTML if I like. In fact, I find that I use the traditional modular CSS approach of using multiple classes, if necessary, in my markup much more often than I extend classes in my CSS. Again, the less custom CSS the better. If I can style an element appropriately just by adding a few helper classes in my markup and stay out of my stylesheet, I win.

Also, the argument over semantic class names is, in my opinion, a red herring. Semantic markup is important in communicating the meaning of a webpage and is only becoming increasingly important; however, class names are for the developer. The exception to this relates to the use of microformats, in which case it is necessary to use specific semantic class names. It’s always important to consider names and what they communicate to you, your team, and future developers, but there is no dogmatic reason to avoid classes like “grid-1” or “pull-left” just because they describe presentation. People have conflated the use of semantic HTML (which relates to optimizing content for assistive technologies, browsers, the multitude of devices, and software that recontextualizes and reframes your content) with avoiding presentational class names for years, and I’m not quite sure why.

In terms of performance, targeting a class in CSS is much more performant than using descendent / child / sibling selectors, qualified selectors, and even tag selectors, which would be evident of a less-modular approach.

Sass

It’s been a couple years since we’ve made the transition from vanilla CSS and/or LESS to Sass for all of our projects, and we haven’t looked back. Here are a few Sass features and how they relate to modular methodologies:

@extend directive

Once again, the @extend directive tells one selector to inherit all the styles of another selector. The developer can write CSS declarations that can be extended into a single rule and can therefore avoid the use of multiple classes on one element.

@import and Sass partials

According to the docs, “Sass extends the CSS @import rule to allow it to import SCSS and Sass files. All imported SCSS and Sass files will be merged together into a single CSS output file.” We can organize our CSS into multiple Sass modules, or partials, but eventually deploy a single stylesheet which therefore requires only a single HTTP request.

Caveat: over-nesting

Although it’s tempting to nest selectors 3 or 4 or 5 levels deep, this can result in a CSS nightmare. Firstly, the resulting CSS will be longer and therefore more time-consuming to parse. Secondly, your CSS selectors will most likely be much more specific than necessary, which makes modularity nearly impossible.

Next Steps

Modular CSS is a challenging topic and is much more of a journey than a destination. For the last year or so, we’ve been attempting to write more modular front-end code and we’ll continue to improve our process. A next step for us will be to start paying a bit more attention to naming conventions. BEM, OOCSS, and SMACSS all suggest naming methodologies based on parent/child relationships and states. Anything that reduces friction is a good thing, and if following a pattern speeds up development by eliminating some of the guesswork, then it seems like a change for the better.

Conclusion

This is definitely a work in progress. Brian, the other front-end dev at PA, and I often have conversations about our approach to CSS, what we feel is working, and what needs to be improved. Thoughts? Suggestions? Have you tried this approach? What are we doing wrong? If you’ve experimented with modular CSS, we’d love to hear about your trials, tribulations, and successes.

Have a project that needs help?