How Will Web Components Change CSS Architecture?
With the slow rise of Web Componentsâthe breakdown of interfaces into self-contained chunks of HTML, JavaScript, and CSSâwill we see an evolution (or revolution) in how we manage the way we write, build, and bundle the CSS for our web sites?
Currently there are two main approaches to writing CSS: component-based and utility-based. (Iâve also seen this referred to object and functional CSS, respectively.)
Component-based
A component-based approach establishes a 1-toâ1 relationship between the HTML and the selectors. It does so by codifying a design pattern and applying it to an HTML element.
For example, a button is codified in the CSS with a .button
class and applied to an element.
Since thereâs a selector for every design pattern, as the number of design patterns on your site grows, so does the size of your CSS.
Theoretically, thereâs a cap to the number of design patterns you will or should have on your site. However, evolving designs and growing sites often continue to add to the codebase without removing old designs. Iâve seen sites with ten years worth of CSS that continued to be cobbled together.
SMACSS falls squarely in this camp.
Utility-based
At the other end of the spectrum is a utility-based approach. It establishes a 1-toâ1 relationship between the selectors and the CSS properties.
For example, a buttonâconsisting of a collection of CSS propertiesâreceives a number of classes to style the HTML.
There are only so many CSS properties and only so many values we set with those properties. As a result, the size of the CSS reaches a cap.
Atomic CSS falls squarely in this camp.
In the Middle
Of course, there are people (er, most people, probably) that choose to blend these two styles together. Some use a component-based approach for some things, like buttons and inputs, and then use a utility-based approach for other things, like layout and spacing.
Delivery
How that CSS actually gets delivered to a user is a factor in all this.
Most projects Iâve seen go all in. All of the CSS for a project is bundled together into a single file, minimized, then cached.
When I was working at Yahoo!, the reason for the component-based approach was to be able to bundle only the CSS needed for the page and no more. Only when new pages with new components were loaded was the CSS for those components loaded. This was done through a âcombo handlerâ that could combine the individual CSS files together at request time and cached.
Web Components
If youâve looked into Web Components, that last bit should feel really familiar.
If a Web Component is only requested when itâs used then the embedded CSS will only be used when the Web Component is requested.
Web Components actually consist of 4 different technologies: custom elements, HTML imports, Templates, and Shadow DOM. When I refer to Web Components in this article, I refer to them as a collective whole. An actual project not using HTML imports, for example, might use a different strategy for bundling and loading components into a project. A project could still bundle the whole app into one fell swoop like many people do today. In which case, none of what Iâm talking about here really applies.
That means that a component-based approach allows us to localize CSS to a given component and get the performance benefits of only using that CSS when itâs needed.
Many in the React world using inline CSS are essentially doing the same thing. Theyâre writing CSS in the component and that CSS only gets used when the component is requested.
As you can probably guess, my approach (with SMACSS, natch) to building a site using Web Components doesnât really change. Some concerns like using naming convention to namespace CSS fall by the wayside due to the Shadow DOM.
For those using a utility-based approach will still need to go through a bundling process but with the file size being (theoretically) reasonably sized, this isnât really an issue. Each Web Component just has to say that it wishes to use the same CSS file.
Performance
It remains to be seen whether a micro-delivery approach will create a better user experience than a macro-delivery approach.
Does 240KB of CSS (using a component-based approach) broken down into a dozen requests of 20KB each over multiple pages create a better experience than a single 50KB request (using a utility-based approach)?
Iâve seen pros and cons to both scenarios. The micro-delivery approach currently depends on http2 taking off (which it is and will) and while the performance improvements look good overall, weâre seeing that itâs not necessarily an instant panaceaâ â¡. Weâll continue to see server-side optimizations that can be introduced to improve delivery performance.
â Khan Academy saw a performance drop from serving up too many files over http/2.
â¡ Dropbox saw a decrease in performance with POST requests, which has subsequently been fixed.
(I donât mean to be alarmist over http2. I honestly believe that these are small hiccups and that we should be moving to http2 as soon as we can.)
Conclusion
All that to say that I donât think the CSS architecture landscape will really change much. Weâll likely see more discussion around what should be defined with a Web Component and what should be defined outside of that. Although, itâs possible that some completely different approach could be introduced.