Reusable, Maintainable, and Modular CSS
A few advantages of CSS are it’s a declarative, readable, easy-to-use nature. It’s not that hard to start writing CSS and seeing results. Although the barrier to entry is low, there are some significant shortcomings that makes CSS difficult for reusability, modularity, and maintainability. Features like nested selectors can be tempting to use but lead to brittle, difficult to maintain code that doesn’t stand up well to changes in the HTML. There also isn’t a single standard to use when making organization decisions for your CSS. In this article, I’m going to shortly go over some methodologies that are commonly used to organize CSS at scale. I’ll then explain the concepts behind those architectures, and how this could help you make your own system for organizing CSS!
Methodologies
- BEM
BEM is very widely adopted, and is still gaining momentum. It includes three key elements
- Block
A block in BEM methodology refers to a “A functionally independent page component that can be reused.” (from BEM documentation). This could be a menu, header, or sidebar. Blocks can also be nested inside each other. For example, you could have a header-menu__search-form
inside of a header-menu
or a sidebar__list
inside of a sidebar
. Each block should be composed of multiple elements that have their own individual styling.
You create a block if you want to reuse the section of code and it doesn’t depend on any other entities on the page to be implemented.
- Element
Elements are the smaller components that are combined to create a Block. Using the example above, a search-form
block would probably contain a few elements like search-form__search-label
and search-form__search-input
. In BEM, elements are also nest-able, so you could have a search-form__search-content
element that contains the search-form__search-label
and search-form__search-input
elements. The nesting structure of elements and blocks depends on your preference and is flexible in it’s implementation.
You create an element if your section of code cannot be reused without being inside a block.
Blocks and elements together create the layout and style structure for your page(s). Something to keep in mind when composing your CSS with this method is that Elements shouldn’t be used outside of blocks. Take this example from the BEM documentation:
- Modifier
While the Block and Element entities are related, Modifiers have a different role in BEM. According to the documentation, modifiers “define the appearance, state, or behavior of a block or element”. An example could be a search-form_focused
or sidebar__list_expanded
. A rule to remember is that a modifier cannot be used without a corresponding block or element.
The BEM methodology is great because it provides in-depth structure for organizing your CSS, but still allows you flexibility in how you nest blocks and elements and how you use naming conventions. To go deeper in how to use BEM, check out the documentation here!
2. SMACSS (Scalable and Modular Architecture for CSS)
SMACSS was created by Johnathan Snook and presents a flexible way to implement modular and organized css. It consists of categorizing CSS rules into these categories:
- Base rules: The base category is used to define defaults for single elements. A good example of base rules is the
reset.css
file that many are using. It’s the bare defaults of how the elements on your page should look. While using base rules that other people created can be convenient, making your own based on your own default style choices can be advantageous as well. - Layout rules: These refer to the major layout components in a page. An example would be the
header
,footer
, orcontent
sections of your page. Layout rules can be composed of many different module rules, the next category in SMACSS. - Module rules: If layout rules are the major components, module rules make up those major components. Modules are your
menu
components inside the majorheader
component, or theform
in yourcontent
layout rule. A key to remember with modules is that they should be designed to exist as a standalone component, without being chained to a certain page layout. This means aform
component shouldn’t care about how it’s parentcontent, footer, and header
are layed out together. - State rules: these are quite self-explanatory, as they describe the state of a module or layout component. These are the rules like
is-hidden
,error
, orsuccess
that provide feedback to the user. These rules imply a javascript dependency as they are toggled with user interaction. When you want to pair a state with a specific module, put the state rules with their accompanying module. For example, you’d put anactive-tab
state with thetab
module. - Theme rules: These rules are used when you want different themes for different sections of the site. While the default styles would be in the base and module sections, if there’s a section of the site with a different theme you apply the different colors, padding, or typography in the
theme.css
file.
SMACSS was a little confusing to me at first, but I downloaded the e-book off the website and it helped me understand it’s principles more. The two main things to keep in mind when writing SMACSS is to avoid deeply nesting selectors and keep the categories of CSS separate as much as possible.
3. OOCSS (Object oriented CSS)
Object oriented CSS is the last, but not least method I will discuss. It anchors around two key principles
- Separate structure and skin
This principle refers to the separation of the layout, or structural css with the visual or skin css. By doing this, you can have a wealth of utility css classes that add semantically meaningful visual changes to a module (layout component) without worrying how they will change when the layout changes. This is because the visuals won’t change when the layout does.
- Separate container and content
This principle revolves around styling your content (like a <h2>
tag) separately from the container that it’s in (like a header
element). Check out this example to see how it’s done
// Container dependent CSS (nested selectors)
.myHeader > h2 {
//style here
}// Container Independent css .heading-text {
// styles
}// Now, add the .heading-text class to the h2 element you're trying to style!
Those are the most common methods out there! I suggest you browse around and choose the one that best fits your fancy. For a comprehensive list on css organization, check out this article on CSS tricks!
Patterns in methodologies
Going through the ways other people organized their CSS, I saw some individual concepts being repeated a lot.
- Avoid nested selectors
When trying to get a style to work, many people created highly contextual styles that depend on a certain structure of nested elements or classes to be applied. This looks like so:
// If i'm trying to set the height for a list icon
li span {
width: 32px;
height: 32px;
}
This approach comes with a few issues. One, if I change the span element to an i
or svg
, the style doesn’t work. Two, if I want to apply that style to an Icon outside of a list, I have to write it again. Three, if I want to put something else in the span
it will automatically inherit this style when it’s inside a list. I can solve this issue by taking the style outside of the layout context:
.size-32px {
width: 32px;
height: 32px;
}
Now, i’m not constrained to using a single element or html structure for my list-icon! And, I can reuse that class wherever I want an element to be 32 by 32 pixels. Flexibility, code-reuse, and less confusion!
- Consistent naming conventions/CSS rules categorization
This is an underrated but huge factor in organizing your CSS. Are your names for layout modules marked in some way? How about visual styles? You can do this with prefixes, suffixes, or however else you choose. But, remember that your CSS rules should be categorized. This categorization helps new developers (and future you) figure out the use cases for each CSS class without too many comments. The way you display the categorization of your CSS is with your custom naming conventions!
Remember that no method is a silver bullet, and you have to use a system that works with the project’s complexity, scale, and others that are working on it with you.
That’s all I got! I hope you got some value out of this article. If you did, please leave it a few 👏 to show your appreciation! If you have a cool way to organize your CSS, please share in the comments or message me 😃.
Some resources for future reading on this topic: