When styling applications with global CSS stylesheets, generic class names become specialised over time (e.g. section_heading__active
), and eventually cause problems when a style change in one part of the app accidentally affects usage of the same class name in another part of the app.
Importantly, when authoring app components, you don’t know (or want to know) what CSS classes are being used in the rest of the app.
When authoring components in JSX it’s tempting to just write inline styles, but these can be slow and make the element code more difficult to read.
There are some standardised solutions to this - scoped styles in Shadow DOM - but lack of browser support means that JS polyfills are required.
Another alternative is CSS Modules: when a CSS file is imported into a JS file, the class names in the CSS file are replaced with globally unique names and are provided as an object*.
A solution: CSS in JS
Define the styles inside the component and inject them with a Higher Order Component, generating unique class names at the same time.
In order for components to be themeable, there needs to be a way for theme variables to be available when writing styles*. A theme provider HOC makes the theme object available via React’s context
, so the variables can be used in styles.
There are a few leading contenders:
- styled-components: write styles in CSS, interpolate theme variables, injects a
className
string containing a single class name. - react-jss: write styles in JSS (objects), use theme variables as values, injects a
classes
object containing multiple class names. - styled-jsx: write CSS in
<style>
tags, scoped to the parent component. - material-ui: uses
react-jss
and adds an name to each style object, allowing any class to be targetted for overriding by the theme.
Further reading
- CSS Modules aren’t currently supported by
react-scripts
. SASS is one way to define and use global variables in CSS, but is also not currently supported byreact-scripts