CSS Architectures, Part 2: The Top Scalable and Modular CSS Approaches

Denise R. Jacobs | March 21, 2013

 

As the online industry matures, so do approaches to dealing with code for large Web sites. Cleaner CSS is a great starting point, but front-end developers can elevate a site’s stylesheet to another level by applying methodologies that are part of increasingly popular scalable CSS architectures. By using an approach in its entirety or by applying selected tenets and practices from them all, you can say good-bye to problems that typically plague the CSS for large sites, such as verbose and difficult to read code that’s painful to maintain and update and the redundancy that creates code bloat.

Diagnosing the Origins of Bloated CSS

If you recognize any of the following symptoms or ailments, making your stylesheet modular and more scalable is just what the doctor ordered. To get a proper handle on just how bad things are, search for certain properties and see what the numbers tell you. In Nicole Sullivan’s presentation, the Top 5 Mistakes of Massive CSS, she provides a rubric to diagnose the roots of an overabundance of several key properties:

  • A large number of floats means there is an ineffective or nonexistent grid.
  • A large number of margins means you need a reset.css (or normalize.css).
  • A large number of padding means that the design parameters aren’t explicit and thus multiple developers have tweaked details a lot.
  • A large number of font-size means that the cascade is not being leveraged. Headings are probably hidden within the rule sets with font-size as well.
  • A large number of !important means that this property is being used to override specificity and, again, that the cascade is not being leveraged.

Any of this sound familiar? It’s okay, you’re in good hands, because now that you’ve diagnosed the origins of your CSS bloat, we can talk about some sure-fire cures.

Scalable and Modular Approaches: The Essentials

The main concepts of the different scalable approaches can be boiled down to two core practices:

1. Reduce, Reuse and Recycle

Reducing means writing the shortest chain of elements possible in selectors, and dropping element qualifiers, much of which I discussed in the previous article. Equally important is creating appropriate selectors by favoring classes over IDs, avoiding the use of elements, and using combinator selectors that more directly target the element you need on the page.

Reusing involves creating generic classes instead of overly specific ones, and combining classes to create different visual outcomes.

Recycling involves better leveraging the cascade to cut down on redundant style declarations, modularizing page components to use throughout the site with minimum code and extending modules through subclassing.

2. Organize, Structure and Inform

Providing good, well-organized information is critical for clarity and understanding. The practices listed in the first article, like providing developer information in the stylesheet and creating a structure in terms of the document itself (by categorizing styles in the document), play a part in the scalable approaches. However, developers can add even more structure by breaking the style categories into multiple documents, indicating structure and meaning through a naming convention for reusable classes and establishing page structure with grids. Web site style guides are the final component for making sure the team is well informed about styles, structure and nomenclature.

An Overview of Scalable and Modular Approaches

Now that I’ve introduced the key concepts, let’s take a look at specific practices that support these concepts through an overview of the best-known and most popular approaches to dealing with large CSS projects. The approaches I’ll cover are DRY (Don’t Repeat Yourself) CSS, Object-Oriented CSS (OOCSS), Scalable and Modular Architecture for CSS (SMACSS), and CSS for Grownups.

DRY CSS

The ease of learning and applying CSS is mitigated by the language’s lack of logic. Unlike programming languages that have reusable components like variables and functions, CSS almost encourages flagrant reuse of selectors and property-value pairs. Indeed, even when redundant and bloated, CSS is perfectly functional.

DRY CSS is based on taking the “ don’t repeat yourself” principle of software development very literally. That’s right: when coding CSS, the goal is never to repeat a property-value pair. Ever. I know it seems rather…ah, intense, but it can be done. 

Get Your Group On (So to Speak)

The core of DRY CSS is grouping, which at its roots entails structure, organizing, reducing and recycling. Jeremy Clarke, who devised DRY CSS, suggests creating groups of selectors with shared properties, rather than repeating property-value pairs for each selector separately, as is typical when writing CSS. While a group may have many selectors, each property-value pair is defined only once.

The groups actually define shared properties. With DRY CSS, you have to relinquish the deeply ingrained habit of naming classes and IDs based on semantics, like .alert-box for example. Instead, groups use descriptive names based on their appearance or on their role in the design—like .rounded-corners—but then all selectors that share that property should be grouped with that style. While doing this takes away the possibility of mixing and matching, it does lessen the amount of your code.

How do you create a group? Start by naming the group based on its role in the design. Then use the name of the group as an ID at the top of the list and a class at the bottom. Then add the rest of the selectors that share properties above the descriptive class name that they share. Jeremy gives the example shown in Figure 1 in his presentation “ DRY CSS: A don’t-repeat-yourself methodology for creating efficient, unified and Scalable stylesheets.”

Example of DRY CSS groupings
Figure 1.Example of DRY CSS groupings

What about selectors that don’t immediately seem to be part of a group? Another goal in “drying out” your CSS is to make individual selectors as rare and sparse as possible, employing them only as exceptions. This means you need to perform a mental exercise when you’re coding. As you create a style declaration for a selector, always ask "Why isn’t this part of a group?"—and then figure out how to make it part of a group if you can.

Once you create groups, you need to think about organizing them. Clarke recommends using colors, text, shapes, structures and modules as categories, but he also encourages developers to create whatever categories they feel are best for a project.

Benefits

In his presentation on DRY CSS, Clarke lists many benefits to the approach. Here are some that I feel are most compelling:

  • Decreases the size of CSS files. Clearly, this is the prime objective, and by using DRY CSS you more than achieve it.
  • Optimises elements and generalizes selectors. The occurrence of this increases as you see their interrelatedness and how they can be inherited.
  • Edits to a group affect all its members, which encourages consistency. You can see the members of a group change at the same time, which is a great advantage over making changes to a lot of individual selectors.
  • The HTML remains untouched. This is useful for sites with generated HTML that can’t easily be controlled, such as content management systems or blogging tools.
  • Encourages thinking through design elements/styles and design patterns and the consistency thereof. This promotes good design practices and uniform updates.

Clarke also asserts that DRY CSS integrates with other scalable architectures, such as OOCSS and SMACSS.

Successes

Clarke had great success applying his approach to the Global Voices site, which also had to support localization into multiple languages. According to Clarke, in developing and applying DRY CSS, the site’s stylesheet went from roughly 4,500 lines to 2,400 lines. That’s an improvement that most front-end developers would welcome.

OOCSS

Object-Oriented CSS starts with pattern recognition: determining what page elements are similarly structured and used frequently on the site. Once a pattern is identified, the design element can be made into a module. Then the module can be skinned for the different ways it shows up across the site.

OOCSS has two key principles. The first is to separate structure and presentation (or structure from “skin”), which means decoupling the structure of an element from its looks, and treating the looks like “skins.” This principle shouldn’t be too difficult to implement, as it’s similar to one of the foundational tenets of Web standards: the separation of presentation and content.

The second principle is to separate the container and the content, which means to use styles that are specific to an element and don’t depend on location. All too often, the common way to create CSS selectors is to attach an ID or a class to an element high in the DOM (like <body>), and then to create long-chain selectors to create variations on elements. This practice is responsible for most heinous CSS transgressions that lead to unwieldy and difficult to maintain stylesheets. Instead, in OOCSS, a container is modified by extending it, which effectively alters the container based on the content. In other words, you add an additional CSS class to provide for the differences in appearance only.

Sullivan breaks down the OOCSS approach into the following steps:

  1. Determine the reusable elements sitewide, such as headings, lists (action list, external link list, product list, or feature list), module headers and footers, grids, buttons, rounded-corner boxes, tabs, carousels, toggle blocks.
  2. Delineate between:  
    • Container and content
    • Structure and skin
    • Contour and background
    • Objects and mixins
  3. Mix and match container and content objects to achieve high-performance design.
  4. For visual differences, skin the modules. Skins/themes are the module’s presentation—how it looks. The goal is to have very predictable skins, changing only values that can be easily calculated or measured.

Modules: The Building Blocks of a Site

Much of the practice of OOCSS is built on reusable components. Sullivan likens these components to Legos and refers to them as modules. The goal for a module is that it relies neither on the DOM tree nor on specific element types. It should be flexible enough to adapt to different containers and be skinned easily.

Identifying, creating and employing a module is a very DRY aspect of OOCSS. By finding common elements and presentations and abstracting them into reusable code modules, front-end developers don’t repeat themselves and really do practice reducing, reusing and recycling.

An excellent example of a module that can take care of images with text in various forms and incarnations is Sullivan’s .media module. The .media module was developed to handle instances of images floating off to the side of text and related permutations. She gives this example of various forms that the media module can take (see Figure 2).

Figure 2. Various forms of the .media Module

Here is the HTML that forms the structure of the media module:

<!-- media -->
<div class="media">
  <img class="fixedMedia" src="myimg.jpg" />
 
  <div class="text">
...
  </div>
</div>

The CSS of the initial module establishes the basis of the style, and any differences come from extending the styles and thus the appearance of the elements.

/* ====== media ====== */
.media {margin:10px;}
.media, .bd {overflow:hidden; _overflow:visible; zoom:1;}
.media .img {float:left; margin-right: 10px;}
.media .img img{display:block;}
.media .imgExt{float:right; margin-left: 10px;}

The media module is just the tip of the iceberg. Many more modules, including buttons, grids, carousels, and content, are on the OOCSS project on GitHub.

Benefits

Adopting OOCSS, or at least elements of the system, saves many lines of code. Furthermore, it provides an approach that is easily sandboxed and can be used by everyone on the team.

Successes

One of the biggest and most famous sites that Sullivan has applied OOCSS to is Facebook. According to the numbers given in her presentation CSS Bloat, she and the Facebook team cut CSS bytes per page by 19 percent and HTML bytes per page by 44 percent. Just with headers alone, they reduced the number from 958 to 25, and reduced the site’s response time by half.

SMACSS

SMACSS ( https://smacss.com/) is another approach to writing scalable and modular CSS for large-scale sites. According to Jonathan Snook, its creator, “ SMACSS is about identifying patterns in your design and codifying them.” Sure, I’m biased, but we could take “codifying” patterns as simply another way of describing the core tenants (reduce, reuse, and recycle; organize and structure), could we not?

Snook has several practices for applying organization and structure to large CSS projects. The core of SMACSS is the categorization of CSS rules. Categories help design patterns become more obvious, thus enabling developers to make better definitions for and of these patterns.

The categories that Snook suggests are:

  • Base—These are defaults styles, usually for single element selectors.
  • Layout—Divides the page into sections, usually holding modules together.
  • Module—Reusable, modular parts of the design: callouts, sidebar sections, product lists, and so on.
  • State—Describes how the module or layout looks in a particular state, also in different page views.
  • Theme—Describes how modules or layouts might look.

In small projects, these can all be in the same file. In larger projects, multiple files are recommended.

However, there is a trick with the categories, and it involves thinking about what the styles actually do and what part of the site, design and functionality they apply to. This forces developers to ask during the building process “How are we going to code things, and why are we going to code them this way?” Thus, implicit in the categories are guidelines on how the styles are used, which further helps to prevent mixing styles across categories.

What’s in a Name?

The next important part of SMACSS is naming style rules. Clear class names are one of the key ways for knowing the category that a style rule is part of and what it does in the grand scheme of the page.

To indicate the differences between layout, module and state styles, Snook suggests appending prefixes to the class names. For layout, for example, you would add l- or layout-, creating a class name like .l-aside or .layout-aside. To indicate classes that create a state change, use .is-state, such as .is-active or .is-collapsed.

When creating names for modules, which include navigation bars, carousels, dialogs, widgets, tables, icons and so on, use the name of the module itself. For instance, an example module would be called, appropriately, .example (note that it is a class and not an ID). A callout module would be called .callout. If you need to add a state to a module, you know what to do: add .is-state, so, a collapsed callout module would be .callout.is-collapsed.

What about extending (or subclassing) a class? Easy. Instead of using a module’s class name as part of a combinator selector (and thus creating specificity issues), create a new class name based on the original class. For example .pod is extended by creating .pod-callout, and then you apply both styles to the element. With the new style, both styles have the same specificity, and thus the new style rules can play well with the first one.

Focus on Good, Clean Code, and Don’t Worry About “Classitis”

Clearly, one of the objectives of SMACSS (much like OOCSS) is to create shallow instead of deep selectors with the fewest generations of elements, striving for the shallowest selector possible. If you follow the recommendations in the first article in this series, you’re well on your way. But a little reminder never hurts, so to help limit the number of elements in a selector, follow these rules:

  • Avoid tag selectors for common elements unless they are completely predictable. Using a class is preferable, even if you think the element is going to stay predictable. This includes qualifying classes with elements.
  • Use class names as the right-most (key) selector.
  • Use child selectors (e > f) instead of descendent selectors (e f).

Another goal of creating shallow selectors is to eliminate issues with selector specificity. One of the primary ways to ensure that you won’t have any specificity wars within your CSS is to avoid IDs for selectors. Don’t dismiss IDs completely, however. In SMACSS, it’s okay to use them for layout sections and for JavaScript hooks.

Some of us have had the old-school best practice “Don’t use too many classes!” deeply ingrained into our front-end development psyche. However, when it comes to SMACSS (and most of the scalable CSS approaches), you’re better off adding classes to the elements in question and repeating the class in the HTML than you are creating and applying a bevy of overly specific styles, which is the true cause of classitis. You’ll find that using multiple well-named classes clarifies intent and increases the semantics of the elements in question.

Benefits

The benefit of SMACSS is the clarity that comes from being conscious about your coding from the very start. Categories help slash redundancy, and naming conventions greatly aid efficiency in quickly identifying style rules in the CSS.

Successes

Snook developed SMACSS from his experiences working on enormous Web projects, one of the most notable being the redesign of Yahoo mail. He has had great success applying his principles with large sites built by large teams.

CSS for Grown Ups

Andy Hume, the creator of CSS for Grown Ups, jokingly refers to his system as “CSS for grumpy old people.” (You can watch a video here.) Like many of the creators of scalable approaches, Hume is concerned that our industry has become married to archaic, so-called best practices (most, ironically, created by developers who worked alone). He thinks that front-end developers have trudged unwittingly down a path that creates CSS that is feared and despised in most projects. This front-end code adheres to Web standards at ridiculous lengths to keep content and session separate, but it pays no mind to managing style and project complexity.

It’s clear that we need to optimize code for change. With CSS for Grown Ups, the goal is to style modules, not pages, and to go a step further by having a style module library that you can reuse.

Layers, Like an Onion. Or Cakes (or Parfaits) *

Much like the use of categories in SMACSS, CSS for Grown Ups describes styles being in “layers.” A style’s layer is related to:

  • Document—From HTML code, element selectors.
  • Base styles—Applies to element selectors, typographical styles, colors.
  • Module styles—Lists, navigation, promo box, and so on.
  • Layout styles—Establishes the grid or columns and page layout.

When creating selectors, be aware of whether they are document, base or module selectors, and make an effort to keep them all at the modular level. How will you know? If there is a tag as part of the selector, it will be a document style. However, if you create a class for it, you release it from the tag and make it a module style.

The goal is to try to avoid styles that are document-, base- or layout-related, and to shoot for ones that are module-related instead. Why? Let’s look at an example:

.promo-box h2 { ... }

This selector is a module-level selector (.promo-box) combined with a document level selector (h2). This is all well and good at the outset, but what if somewhere down the line the structure of the HTML changes?

Instead, we should be shooting for the document and the module to be less tightly coupled so that the selector can be scaled in the future. This example does just that:

.promo-box-h { ... }

In this instance, the style is not tied to a document’s element, and is thus far more flexible and portable, as it can be applied to anything, even elements that haven’t yet been invented in HTML.

Free Your Selector Name, and the Rest Will Follow

It should not surprise you that CSS for Grownups epitomizes the tenets of organize, structure and inform. According to Hume, styling with clear, informative class names is “like an API into your document—an API lets you style your document in the most simple and efficient manner.” Class names should be descriptive and should have meaning within the context of the site you’re working on. They should make sense to the members of the team working on the site so that you know which shared terms to reuse.

Like the other approaches, CSS for Grownups advocates creating and using modules. And like OOCSS and SMACSS approaches, the names of the modules should be descriptive and semantic and not tied to location or appearance:

.promo-box { ... }

CSS for Grownups has a methodology for extending or substyling a module. Just use the module’s name, append it with two dashes (--), and add a clear, informative name for the extension, like so:

.promo-box--light { ... }

The two dashes indicate that the style is an extension of the first and also that it is dependent on the first. Thus, it must come after the first style in the source order of the CSS in order to overwrite one or more style rules in the original.

Use Helpers. Be a Sharer

To handle presentation issues, Hume recommends using “surgical layout helpers,” which are standalone classes that provide either padding or margin. Here’s an example:

.margin-top {margin-top: 1em;}

This would be the style you could add to whatever element needed it on the page, instead of wrapping that style into a component. Then these classes can be used on a case-by-case basis when a module needs to be spaced vertically on a page. Use these helper styles in your base stylesheet so that they can be used easily throughout the project.

Finally, writing online style guides is strongly recommended as a way to codify the naming and structure established and to disseminate this information to the team, making it available for those who will work on, add to and alter the site in the future. The style guide and corresponding module library needs be in code so that team members don’t have to reinvent the wheel to implement repeated visual styles.

Benefits

As Hume stated in his presentation at SXSW 2012, “Nobody is really smart enough to style web pages.” And because of this, he argues that we need certain constraints and parameters such as those supplied by CSS for Grownups. Constraints are good—they are a way to manage complexity. Hume developed CSS for Grownups as a way to manage complexity of CSS over large sites, over time and amongst teams of developers. Furthermore, CSS for Grownups creates what Hume calls a “design-meets-development touchpoint,” where the design language of an organization is turned into code, and clear collaboration from both teams results in a higher-quality product.

Successes

CSS for Grownups has roots in the vast amount of work that Hume did while he was at Clearleft, which has had many large clients, such as Channel 4, Amnesty International, and Mozilla. Now that he is at the Guardian, he has successfully applied his system to create a framework for the front-end developers there.

Progress, Not Perfection

In his presentation Breaking Good Habits, Harry Roberts accurately states that “CSS is such a mess that even when you clean it up, it’s still a mess.” Our goal is to make our CSS better, not perfect. So look at each of these approaches with an open mind. Remember, the point is not to drive yourself crazy trying to get your CSS to fit perfectly within some methodology. Even if you adopt only some of the techniques, you still gain the benefits of fewer lines of code that will scale.

The scalable and modular approaches all have pieces of genius and brilliance to them, and are particularly great when you are starting to code a project from scratch. But what do you do when you have to deal with a mountain of existing CSS, whose sheer immensity strikes fear in your heart? The next article will share a process to coax order and sanity into the wildest of CSS beasts, so stay tuned!

Links for Further Reading


This article is part of the HTML5 tech series from the Internet Explorer team.  Try-out the concepts in this article with 3 months of free BrowserStack cross-browser testing @ http://modern.IE


About the Author

Denise R. Jacobs is an expert in Web design and is an industry veteran with more than 14 years of experience. She is now doing what she likes best: being a speaker + author + Web design consultant + creativity evangelist. Most appreciated on Twitter as @denisejacobs for her “great resources,” Denise is the author of The CSS Detective Guide, the premier book on troubleshooting CSS code, and coauthor of Interact with Web Standards and Smashing Book #3: Redesign the Web. Her latest pet project is to encourage more people from underrepresented groups to Rawk the Web by becoming visible Web experts.  You can reach her at denise@denisejacobs.com and see more at DeniseJacobs.com.

MSDN Magazine Blog

MSDN Magazine Right Rail

14 Top Features of Visual Basic 14: The Q&A
Leading off the feature in the January issue of MSDN Magazine is Lucian Wischik’s fantastic look at Visual Basic .NET 14. As Wischik writes, the newes... More...
Wednesday, Jan 7
Big Start to the New Year at MSDN Magazine
Folks, things are hopping over here at MSDN Magazine. We are kicking off the new year with a pair of issues: Our regularly scheduled January issue and... More...
Friday, Jan 2

More MSDN Magazine Blog entries >


Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.