Inefficient web styling slows performance, adds inconsistencies, and harms developer and designer productivity. But many teams don’t prioritize CSS tech debt; gains are subtle and hard to measure. And CSS testing suites aren’t as robust as those for JavaScript, Rails, and other web languages.
Yet the effort necessary to keep web styling lean and efficient is overblown. The key is abstracting page level styling into reusable components.
Components are distinct groups of elements on a page. Common examples include navigation bars, carousels, and form sets. Components should be standalone, easily moved to different pages without breaking layout. Some styling methodologies substitute other terminology for components, calling them modules or blocks. And the size and scope of component usage differs widely among projects. Large projects, given their size and scope, tend to rely more on components than smaller works.
Regardless of their complexity or classification, components make formerly one off items reusable. The code simplifies while modularity and page speed increase. If you’re not abstracting your styling, you’re neglecting part of your responsibility as a web developer.
That may sound hyperbolic, but I’ve seen firsthand how inefficient CSS can be so harmful. Many developers disagree, given CSS’s footprint is generally smaller compared to JavaScript or imagery. Modern browsers are also more efficient cutting through bad CSS selectors than poorly written JavaScript.
Yet performance is rarely where CSS bloat is most acutely felt. Inefficient styling affects user experience first, because it almost always leans on unnecessary repetition. And more repetition increases the chance of making different parts of a project inconsistent.
Bloat also makes developers less productive. Instead of trusting tight, well organized code, they create their own “one off” solutions. Source maps and other modern tooling can help. But sprawling CSS makes it more time consuming to navigate through code for bug fixes and enhancements.
The beauty of focusing on component abstraction is that it works for almost any project or team. Unlike many articles I read elsewhere, there’s no single magic bullet (e.g. PostCSS, Gulp plugin) being promised here.
I find one of the best ways to tackle CSS abstraction is to ask yourself several questions in the order listed below. Once you reach a “yes”, take actions necessary to flip the questions’ answer from “yes” to “no”.
Does your code lack a clear separation between page and component level styling?
File organization is critical. If you don’t have a good system for where your components are organized, any CSS wins will be short lived. Many common approaches to CSS organization (e.g. SMACSS, Atomic Web Design) assume a file split between components and page styling out of the box. But I’ve worked on several projects where all styling code gets thrown together haphazardly. I’ll see a well thought out component placed alongside some trash page level styling that needed a clean up months ago. That’s not good.
At the same time, you don’t have to rework the organization all at once. Start simple and create a single new folder and empty styling file for your new components. You can always expand to a more complex structure later.
Do two or more identical components rely on different styling?
This question is best illustrated through an example. Let’s say your web project has two different pages with an identical drop-down header navigation. Yet the CSS that styles the navigation is different. In the most egregious case, two different sets of CSS have identical styling under different class names. Or there are different layout techniques to achieve the same visual layout. One version relies on flexbox, the other on floats and clears.
In either scenario, the functionality among all components is the same. it’s time to abstract this styling into a single component. Pick one set of code as a starting point and use standardized class conventions to simplify styling. Once you’ve got the component structure down, rewrite markup accordingly.
Do two or more similar components rely on different styling?
Identical components are straightforward to abstract. There’s a single look and feel. Markup changes alone should do the job. But taking abstraction to the next level requires sniffing out similar components as well.
This isn’t as easy, because there’s many directions to take similar components. For simplicity, one option is to just remove differences entirely. Pick one best version, and convert both components to the same styling and markup. Or preserve the differences by creating a “base” component alongside variations.
And deciding how to abstract similar components is rarely done in isolation. We’re moving beyond code into UX, aesthetic design, and product management. So engage with others on your team. Designers, project managers, and other project stakeholders, not code, can help set future direction.
Is every repeatable component abstracted to a single point in the codebase?
This is the ideal code state. You’re heavily relying on reusable components for your styling. Page level code is only for features that aren’t replicated anywhere else.
Yet your work still isn’t done. Your code is organized, but you team may not be. If most developers are adding styling haphazardly, it’s easy to lose ground. Or the development team is on top of web components, but they are unknown or ignored by the designers. As a result, new comps and designs vary from what came before. The handoff process from designer to developer slows.
So when the code is rock solid, move beyond into education and support for others. First your immediate team. Then buy in from the designers, and other stakeholders you work with regularly.
Reading the questions above may make component work sound intimidating. But in practice, components can start from almost anywhere, and the benefits kick in immediately.
Well organized web styling speeds up your team’s workflow. It also helps UX and aesthetic consistency. Start small, but start somewhere.