Styling React Components
Why I chose glamorous
TL;DR
My goal was to find a maintainable and scalable way to style React components at iFixit. These were the features I was looking for in a React styling system:
- Styles encapsulated within components
- Local by default
- Ability to delete code with confidence
- Style as a function of state
- Support for shared constants (color, spacing, etc.)
- Ability to use native CSS features (media queries, animations, etc.)
I chose to use glamorous, a React styling library, because it addresses all of my wish list items with a simple API.
Goal
To find a maintainable and scalable way to style React components.
Wish List
These were the features I was looking for in a React styling system:
Styles encapsulated within components
I should not have to worry about how a component is styled in order to use that component. Using a component should be as easy as import MyComponent from ‘./MyComponent’
. This means that I won’t have to sync up css files when using components (yay!).
Local by default
Native CSS is global by default. Global styles work great for styling documents but can create problems when styling large web applications. To deal with globals in CSS right now, we have to make sure our class names are specific enough to avoid naming collisions. Naming collisions due to global CSS class names result in unpredictable styling and are hard to debug and fix.
I want the styles I write to be locally scoped to the component I’m developing. This means that I can be confident that my styles won’t bleed into components.
It is really crazy to me that the best practices in CSS is still to use global variables. We’ve learned in JS for a long time that globals are bad.
– Christopher Chedeau, Front-end Engineer at Facebook
Ability to delete code with confidence
I should be able to confidently delete styles and know that I’m not going to break anything I didn’t expect. This will make the code way more maintainable.
Style as a function of state
The typical way we handle state-dependent styling at iFixit is to define state-specific classes (e.g. .button-disabled
) and apply that class to an element conditionally with JavaScript. This method works for simple cases but it can get complicated for more involved use cases. Ideally, I could define the style of a component as a function of the component’s state. This is similar to the way React renders the view as a function of the application state. Here’s an article explaining this concept:
Support for shared constants (color, spacing, etc.)
Site-wide constant values like colors, spacing, font sizes, breakpoints, etc. should be available to any component. A component should be able to import the constants like this: import { colors } from ‘./constants’
. This will enforce visual consistency and limit the number of decisions I have to make while developing.
Ability to use native CSS features (media queries, animations, etc.)
We don’t want to lose any feature that we have now. We still want to be able to use native CSS features like:
- Media queries
- Pseudo classes (e.g.
:hover
) - Pseudo elements (e.g.
::before
) - Relational CSS Selectors
- Animations
Conclusion
After exploring a blackhole of articles and videos, I decided to use glamorous to style React components. Glamorous is a React styling library with a simple API. The project is open source and maintained by Kent C. Dodds, an engineer at PayPal. Here’s how glamorous addresses all the items on my wish list:
✅ Styles encapsulated within components
With glamorous, styles are defined in the same file as the component. This makes it easy to develop and maintain components because all the relevant code is bundled in the same file.
Here’s an example of a simple Button
component styled with glamorous:
Notice that using the Button
component is super simple. No need to handle any separate CSS files.
✅ Local by default
Glamorous uses glamor to generate unique class names under the hood so we can be confident that our component styles are locally scoped.
✅ Ability to delete code with confidence
Because all of our component styles are local, we can be confident when deleting code that we won’t affect any other parts of the app.
✅ Style as a function of state
Glamorous allows us to define styles as a function of the state, like this:
props => ({ color: props.disabled ? ‘red’ : ‘blue’ })
This method is a lot more declarative than conditionally applying classes. Here’s an example of using dynamic styles with our Button
component:
✅ Support for shared constants (color, spacing, etc.)
We can use simple JS constants to share values like color, spacing, etc. Here’s an example Button
component using shared constants:
Notice that we’re just using plain JS to handled shared constants.
✅ Ability to use native CSS features (media queries, animations, etc.)
Glamorous allows us to use all the CSS features we know and love. Check out the Getting Started guide for examples.
Helpful Links
React: CSS in JS
These slides are kind of famous for changing the way we think about CSS. Check this out if you’re thinking: “Why would anyone want to write CSS in JS? What a terrible idea!”
Choosing a CSS in JS library
This is a good overview of all the ways to style React components. Check this out if you’re thinking: “What are the alternatives to glamorous?”
Getting Started with Glamorous
Check this out if you’re thinking: “Glamorous seems cool. How do I get started?”
Have a question or comment? Let’s talk on Twitter: @colebemis