Be sure to click the tabs above to view the source HTML, CSS, and JS. These are basic examples of a news article element, that when clicked, expands to show the article’s content. It’s pretty easy to tell how these elements are going to look from reading the code. The #news-article element’s width is going to be 90% of the parent container, sit in the middle of the parent container, and it also has a few rules to set the color of the text and the background. Any h3’s within #news-article will have a larger font-size and a darker color than the other text within the #news-article element.
Everyone has likely written CSS similar to this when starting out, it is a part of becoming familiar with the syntax of CSS before thinking about higher concepts like maintainability or code reuse. CSS structure becomes important when working on growing sites with a team of developers. Without proper care, this unassuming bit of CSS can turn into a nightmare to maintain.
The problem with this type of CSS? As the site grows, it becomes very specific to the way the markup is structured and very little of the CSS written can be used for other areas of the website. Not to mention, we’re using ids for styling, which opens a whole can of CSS specificity worms.
Stepping away from CSS for a moment, let’s think Object Oriented Programming (OOP). OOP is a method of software design allowing developers to write reusable, easy to maintain modular code. Developers using OOP look for patterns and use inheritance to help simplify and extend applications.
Applying the modular principles of OOP to writing CSS, Jonathan Snook evolved a new-school mentality for CSS process: Scalable and Modular Architecture for CSS (SMACSS).
Pronounced “smacks”, SMACSS is an approach to writing CSS that uses many of the same principles found in Object Oriented Programming. According to SMACSS, CSS rules can be broken down into 5 categories:
- Base - These are defaults that apply to all base elements, like <a>,<p>, or <h1>.
- Layout - Layout rules divide the page into sections.
- Module - Modules are reusable and can appear in multiple locations within the site.
- State - States are associated with modules and update their appearance based on the module’s state or context within a layout.
- Theme - Theme rules tweak how a module looks when a given theme is applied to the site. Most sites do not require a separate theming layer, but some do and we should be aware of it. Theme rules generally only apply to colors or backgrounds.
By learning to classify our CSS rules into one of these categories, it’s possible to ensure that our CSS can grow with the site, and stay easy to work with.
As an example, take a moment to break out some of the above CSS rules into their categories.
Well-designed websites have cohesive design holding every page together. Navigating any non-trivial website becomes unbearable when every page or section uses it’s own different design guidelines. Remember the magenta & lime green days of MySpace? When each user controlled the look and behavior of their page with loud and terrible results…Base styles can set the rules for common HTML elements that should be the same across the website. Breaking out the base styles above should look like something like this:
A full site would have many more base styles than what’s listed above, and probably use a reset or normalize.css to iron out browser inconsistencies, but this is all that's necessary for this example. Pulling these styles out into the base level ensures our typography will be consistent wherever it appears, without having to copy and paste the same rules in multiple places.
In the above example, we’ve attached the width and margin directly to the #news-article element. Continuing to use this method to apply these styles to individual elements will result in having ‘width: 90%’ strewn throughout the CSS. If you wanted to have a news article in a sidebar, or some other area of the page where the width should be different, you would have to override this rule for that particular instance of the news-article. You’ll also want other modules to be able to share this layout, so pull that into it’s own class and wrap the #news-article element in a div with l-full-width class. Prefix this class with ‘l-‘ so the developers looking at the markup immediately know it’s a layout class.
This point is where you’ll separate the #news-article module from other areas of the site. Since this is a basic example, we’ve included just a background color, some padding for the inside content, and a cursor rule to show the user that the element is clickable. These are a collection of rules that will crop up in many areas of the site. So let’s break them into a content-box module that isn’t specifically tied to news-articles and can be more easily applied to other areas of the site. Now add the content-box class to the #news-article element.
Modules make up the biggest chunk of a website, so it is pretty redundant to prefix every module class with 'module-‘. Instead, name each module class with the name of the module, and any rules that apply to other components in the module will be prefixed with that module’s name. So the content class now becomes content-box-text. This way it’s explicitly tied to the content-box module. This is a pretty bare module. It isn’t typical to see such a small module in the wild, but it just goes to show how many #news-articles styles should never have been applied directly to #news-article in the first place.
As the example shows, the developer prefixed this state class with the module name followed by 'is-collapsed'. This immediately indicates that this is a state class and that it's associated with the content-box module. Now the developer can determine whether or not the content is visible simply by adding or removing this class.
Theming doesn’t really fit with such a small example so leave that category off for now, but be sure to be aware of it, and know when it’s appropriate to use.
Take a look at what the CSS has turned into and see the following benefits were gained by breaking apart the CSS rules:
Now the rules are separated into their respective categories and they’re ready to be applied to other elements on the site. Also, by no longer specifying elements by their id’s, the CSS rules’ specificity has been lowered, making them easier to override later if necessary. Overall this CSS is structured so, as the site grows, developers will be able to reuse these styles instead of continuing to write more and more CSS to ensure that new elements match the overall look and feel of the website.
By this point you may be screaming, “But this just destroyed my markup! Now there are tons of classes and an extra container div!” Sound familiar? You should check out SASS and it’s @mixin and @extend directives, which can help keep HTML semantic, and CSS, dry. In addition, SASS can help break out the pieces of CSS into their own files with its @import functionality, allowing users to create a folder structure for CSS that allows for an overview of the site’s styles and find what areas need to be worked on quickly. An example file structure might look something like this:
- main.scss - this is where a users @import all the SCSS files
- _variables.scss - all SCSS variables stored in one location
This is a very compact example. In order to fully grasp having a sane structure to your site’s CSS and how much it can help with your development process, pick up a copy of SMACSS by Jonathan Snook. He’s able to dive into greater detail and offers more robust examples. I've been using this approach while writing CSS for the past year, and it's been a tremendous help in ensuring that my CSS is easy to work with, both while developing the site, and then months of updating down the road.