Key Takeaways
- Embrace scalable and modular CSS architectures to manage and maintain large-scale web projects efficiently, ensuring cleaner, more readable code.
- Utilize methodologies such as DRY CSS, OOCSS, SMACSS, and CSS for Grownups to reduce redundancy, enhance reusability, and keep CSS files lean and effective.
- Focus on reducing CSS bloat by diagnosing common issues like excessive floats, margins, and padding, and addressing them with structured and systematic coding approaches.
- Implement modular approaches by identifying reusable components, which can be styled independently of their environment, promoting flexibility and consistency across web pages.
- Employ clear naming conventions and categorization (as suggested in SMACSS) to make CSS more intuitive and easier to manage, particularly in team environments.
- Consider the use of preprocessors like SASS or LESS to aid in creating scalable and modular CSS, leveraging features such as variables and mixins to enhance code efficiency and maintainability.
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.
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.” 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.
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:- 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.
- Delineate between:
- Container and content
- Structure and skin
- Contour and background
- Objects and mixins
- Mix and match container and content objects to achieve high-performance design.
- 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. 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.
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).
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.
.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
- Structuring CSS – State of Play in 2012
- CSS Strategy Square-off
- CSS Architecture
- CSS ID Selectors: Never Say Never
Frequently Asked Questions on CSS Architectures: Scalable and Modular Approaches
What are the key differences between Scalable and Modular CSS?
Scalable CSS refers to the ability of a CSS codebase to handle growth and change over time. It’s about writing CSS in a way that doesn’t hinder the growth of your project. On the other hand, Modular CSS is a concept where the CSS is divided into reusable modules. Each module is a standalone piece of code that can be inserted wherever needed without affecting other parts of the website.
How can I implement a scalable CSS architecture?
Implementing a scalable CSS architecture involves planning and organization. You should start by defining a clear and consistent naming convention. Then, structure your CSS in a way that separates layout and components. Use preprocessors like SASS or LESS to help manage and maintain your stylesheets. Also, consider using a CSS methodology like BEM, OOCSS, or SMACSS to guide your architecture.
What are the benefits of using a modular CSS approach?
Modular CSS offers several benefits. It promotes reusability, which can significantly reduce the amount of CSS you need to write. It also increases maintainability, as each module is independent and can be updated or modified without affecting other parts of the website. Moreover, it enhances readability and organization, making it easier for other developers to understand and work with your code.
Can I use both scalable and modular approaches in a project?
Yes, you can and should use both approaches in a project. A scalable CSS architecture ensures that your CSS can handle growth and change, while a modular approach makes your CSS more maintainable and reusable. Using both approaches together can result in a robust, efficient, and manageable CSS codebase.
What is BEM and how does it relate to scalable and modular CSS?
BEM, which stands for Block, Element, Modifier, is a CSS methodology that provides a structured naming convention for classes in HTML and CSS. It promotes a modular approach by dividing the user interface into independent blocks. This makes the code more readable and maintainable, and it also supports scalability as it allows for the reuse of code blocks in different parts of the project.
How does a preprocessor like SASS or LESS aid in creating scalable and modular CSS?
Preprocessors like SASS or LESS provide features such as variables, nesting, mixins, and functions that are not available in regular CSS. These features can greatly enhance the scalability and modularity of your CSS. For instance, variables allow you to define a value once and use it in multiple places, making your code more maintainable and scalable.
What are some common challenges when implementing scalable and modular CSS and how can they be overcome?
Some common challenges include managing specificity, maintaining a consistent naming convention, and avoiding redundancy. These can be overcome by using a CSS methodology like BEM, OOCSS, or SMACSS, which provide guidelines for structuring and organizing your CSS. Also, using a preprocessor can help manage complexity and enhance scalability.
How does scalable and modular CSS improve performance?
Scalable and modular CSS can improve performance by reducing the amount of CSS that needs to be loaded and parsed by the browser. By promoting reusability and avoiding redundancy, you can significantly reduce the size of your CSS files. Also, by organizing your CSS into independent modules, you can ensure that only the necessary CSS is loaded for each page.
What is the role of JavaScript in scalable and modular CSS?
JavaScript can play a significant role in scalable and modular CSS. It can be used to dynamically add or remove classes, enabling more complex interactions and behaviors. Also, with the rise of JavaScript frameworks like React and Vue, CSS is often written in a modular way, with styles scoped to specific components.
How can I learn more about scalable and modular CSS?
There are many resources available online to learn about scalable and modular CSS. Websites like SitePoint, Smacss, and StackOverflow have articles and discussions on the topic. Also, there are several books and online courses that provide in-depth knowledge and practical examples.
Denise R. Jacobs is an author, speaker, web design consultant, and creativity evangelist. Based in Miami, Florida, she is the author of The CSS Detective Guide, and co-authored InterAct with Web Standards: A Holistic Approach to Web Design.