Which CSS technique to use — Styled Components, CSS Modules, Component stylesheets, Single stylesheets.
It’s easy to write CSS code but hard to maintain and scale CSS. Over the past years many techniques were developed, techniques came to resolve problems like scalability, maintainability, specificity and performance.
Most commonly there are four techniques available to write CSS, which is explained below with an example:
Write all styles under one single file. Or write CSS per component wise and import it in main CSS file. As shown in the example below
application.scss is one single file and other css files are imported in this.
css-loader . As shown in example below Title is a component and it has a respective
Styled components — https://www.styled-components.com/
It utilises tagged template literals to style your components. It removes the mapping between components and styles. This means that when you’re defining your styles, you’re actually creating a normal React component, that has your styles attached to it. This example creates a simple title component with some styles attached to it.
CSS Modules — https://github.com/css-modules/css-modules
CSS is globally scoped by nature, which means any CSS selector applies to the entire project’s files. This is complicated to maintain in large scale projects. A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. In accompanying example title is component which is applying CSS by styles object like
styles.button which has unique class name for button.
Every tactic has its own pros and cons. The developers at Quintype decided to write all the points and marked each one with respect to the four techniques. Here is the table which shows all the details.
Let us discuss first column points one by one:
Error handling — In styled components, a CSS error will likely result in a JS error that could break the entire page. This isn’t a possibility with the other techniques.
Extract CSS — Extracting CSS from files is easy in others because they are in
.css or .scss in pure css form. But with Styled Components it is not feasible as the CSS is applied via JS.
Critical CSS — It is difficult in single style sheet to extract above-the-fold CSS. But with Styled Components it is not feasible as the CSS is applied via JS. For component stylesheet and CSS Modules it won’t be critical CSS but minimal CSS, if we make smaller bundles with different entry points.
Use pre or post processor — Use of pre or post processors is not a problem with any techniques.
Global Protection — CSS is globally scoped by default so it is tough in single style sheet and component style sheet. Using organisation techniques like BEM or OOCSS can help with this. It is not a problem for Styled Components or CSS Modules because CSS is locally scoped to the component.
Easy debug — Debugging css issue is simple in others as compared to Styled Components.
Doesn’t bloat JS — As we write CSS styles in JS, in case of Styled Components, its kind of make JS heavy and file also big. For others CSS is separate in CSS files so no problem.
Component tree shaking — It is not possible with single style sheet as we don’t know which CSS belongs to which component. For other it is possible because we write CSS per component.
Nesting rules — Nesting CSS rules is applicable to all techniques. For Styled Components nesting can be done like this.
So we decided to use CSS Modules.
What was the concept behind CSS Modules? I highly recommend to read this useful article https://glenmaddern.com/articles/css-modules.
CSS Modules has many benefits, but it has few disadvantages as well like
- You have to use camelCase CSS class names.
- You have to use styles object whenever constructing a className.
- Mixing CSS Modules and global CSS classes is cumbersome.
- Reference to an undefined CSS Module resolves to undefined without a warning.
To overcome all the above issues there is a plugin babel-plugin-react-css-modules. This can be used with CSS Modules.
Integration of CSS Modules with other libraries which is being used in app is tough.
If library is accepting all classnames via props than this is fine like (react paginate) because we can write css for particular classname in CSS Modules. But there are libraries which do not accept classname via props so it becomes very difficult to target the HTML tag which is coming from the library. So for this case don’t pass global CSS rules via CSS Modules.
Here are some links in which people have discussed about How to use css-modules with other global css
So we decided to use CSS Modules for all our apps. We will revisit this after few months and see how it went. Looking forward to an active discussion.
Other useful resources