One Module or Two

An interesting question was asked of me in regards to the SMACSS methodology:

Karl Tynan asked, “What do you do if you want to use the CSS from one module in another module?”

Not being able to see the design Karl was referring to, it’s hard to say exactly what I would do. However, I’m guessing one of two possible scenarios.

  1. Two modules—like a menu and a modal dialog—share some common traits; or
  2. We’re really talking about a single module with minor differences.

Two Modules with Commonalities

One would think that the purpose of modular CSS is to avoid the repetition of a batch of properties across multiple rules. After all, repetition is just another word for bloat. At least, that’s how we tend to equate the two.

When thinking about modular CSS, it’s not about the CSS that is modular, it’s about the design that is modular. Most designs are built from design elements that are repeated throughout the interface.

Just because your menus and your buttons share the same border radius and font size doesn’t mean those styles should be abstracted away into some third class that gets applied to both elements.

Taken too far, you’d be left with a single class for each CSS property and, clearly, that’s not practical.

Modular design is about separating the components of your design such that they can be re-used elsewhere with ease or that they can be altered with ease. (There are other reasons, too, which I talk about in the SMACSS book.)

In this case, I would code the CSS for each module in isolation. They may have some similarities and that is okay.

One Module with Differences

When do you know when you’re dealing with one module that just has some differences? Sometimes it feels like a case of “you’ll know it when you see it”. In actuality, I believe that the Great Semantic Debate obscures how we should name things.

What do I mean by the Great Semantic Debate? We’ve been convinced as an industry that we should avoid naming things “red-background”. It’s not very descriptive and creates a brittle system for maintaining your website. Not naming something “red-background” is a good thing!

Yet, we use naming conventions like nav and menu which don’t describe the content; they describe the container. They describe the design element.

What about a table of products? We’d probably use a class name of products, right? And then for the events table, we’d use a class name of events. What if they look mostly the same? We’d just bundle up our selectors.

.products, .events { }

If these elements are mostly the same then we should use a naming convention that describes the commonality. 

Unfortunately, this is where naming can be difficult. Do we use a class of table? That might be appropriate, although it feels a little redundant. Maybe matrix. Whatever you choose to use, the point is to use a single class to define the consistent pattern. Then the differences are codified in a sub-module.

.matrix { }
.matrix-minor { }

In this case, if I had originally coded this as two separate modules, I’d bring them together under a single module.

Hard and fast

There are no hard and fast rules for recognizing when you’re dealing with one situation over the other. It may require discussion within your team to come up with something that works.

Published September 01, 2012
Categorized as HTML and CSS
Short URL: https://snook.ca/s/1023

Conversation

11 Comments · RSS feed
Miller Medeiros said on September 02, 2012

I do agree that duplicated code isn't always a bad thing, if you reuse too many rules you will end up with a tight coupled system (making changes to one module will affect the other) and that is terrible for maintenance. Modules should be a set of self-contained rules that doesn't rely on external code to work, they should be as standalone as possible if you want greater reuse and less headaches. Avoiding duplication at all cost can be a sign of premature optimization. Make it work first, refactor/abstract later.

Matt Hinchliffe said on September 02, 2012

There will always be a level of overlap but I think it is wrong to worry too much about repetition on your abstracts/modules. Any performance gains would easily be wiped out in creating code that is more difficult to read. Code readability and elegance (doing the most with the least IMO) should always be the deciding factor. Using a pre-processor can certainly have this effect, overuse of SASS's brilliant placeholder selectors and @extend directive may mean your stylesheet contains less rules but may just be spaghetti to your team.

Oliver Joseph Ash said on September 04, 2012

In this case, I would use two modules, that extend from one module. In pure CSS my group selector would be something like: `.matrix, .products, .events { }`, but in practice I would use the `@extend` method of CSS pre-processors like Sass and Stylus.

This way, a back-end developer can build pages using components that make sense in relation to content, without understanding the design or any front-end code. However, if by extending one module and leaving it behind, this opens up the possibility of an author also using the module generically for any other sort of content that is not for products or events.

Alternatively, you might use the placeholder selector/silent classes in Sass so that you just have two modules. In conclusion, I believe it is better to use two modules in this case, because our ‘lego block’ modules need to make sense to anyone authoring HTML (who may not have knowledge of CSS).

Jonathan Snook said on September 05, 2012

@Oliver: Thanks for the great response. I would imagine that having a back-end developer build out components without any understanding of front-end code would lead to more maintenance headaches and a potential lack of consistency. How do they decide what class names to use? When do they use them?

You're asking for HTML code to be developed and for hooks to be placed for CSS with potentially no or little understanding of that CSS. You're constantly going back to the CSS to adjust for new features. Oh, you have .products and .events but now the Customers feature is added. Back you go to the CSS to have .customers @extend something else. This type of thinking results in context-specific code like this:

.customers {
    .highlight { background: url(banner.gif); }
}

You can take advantage of some features from preprocessors like @extend that help simplify this but in the end, they still generate more code than it would take to build a simple design system. .matrix and .matrix-highlight will still be less code and easier to debug and easier to maintain than .customers, .products, .events {} and all the variations of that you might have with sub-components within those.

Shanawaz said on October 03, 2012

Hi I found your site by mistake when i was sirncheag Google for this issue, I have to say your site is really helpful I also love the theme, its amazing!. I dont have that much time to read all your post at the moment but I have bookmarked it and also add your RSS feeds. I will be back in a day or two. thanks for a great site.

orustam said on October 30, 2012

i have 1 question regarding modules and naming. I'm kind of deciding which paradigm should i use for my css. I saw your presentation on adobe.tv and i've read some info about smacss and i kind of like it. About my question :) - You stick to

.module {}
.module-different {}

Would it be bad to use:

.module {}
.module.different {}

In the last case you would have inheritance, or am i missing your point? And it wouldn't work in ie6 but i think it should't concern anyone in near future.

Jonathan Snook said on October 30, 2012

Orustam: The problem with .module.different is that you end up with class="module different". And then "othermodule different". And even "anothermodule different". Which different is which? How do you search to find the .different class that you want? If you're using preprocessors, you end up with .different nested in hard to find places. In the end, it just makes it harder to find things and work with what you're trying to do.

Tharun P Karun said on February 13, 2013

SMACSS book is yours?

Jonathan Snook said on February 13, 2013

@Tharun: Yes, yes it is.

Brett Jankord said on February 14, 2013

Thanks for this post Johnathon, it's helped me clear up some of my thoughts on modules.

I've been using an approach very similar from the book of adding a modifier(sub-module) to a module for different module instances. The only difference from the book is that I am calling (sub-modules) modifiers. I prefer to use the BEM double hyphen syntax for modifiers (sub-modules) and the term modifiers makes more sense in my mind, but its doing the same thing a what you described as sub-modules.

So for example, with .products, .events tables I would come up with a role based class name for my module. I don't mind .table so I might just use that rather than .matrix, though both would work fine. Then I add my modifier to the module.

/* Global styles for all matrices */
.matrix{...}

/* Local styles for modified versions of .matrix */
.matrix--products{...}
.matrix--events{...}

I set up a repo to help collect common/popular naming ideas for modules like .matrix, modifiers, and components, which are what you refereed to here as sub-components.

I'd love to see a post on sub-components, or the inside parts that make up a module. Curious if you prefer to use descendant selectors and nest sub-components:

.matrix .title, .matrix .body

Or do you come up with unique classes for each sub-component?

.matrix-title, .matrix-body

Jonathan Snook said on February 14, 2013

@Brett: I use .matrix-title and .matrix-body. I want to make sure that the sub-components are named in a way that is related to the module it belongs to.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.