The provided content discusses the adoption of styled components in a Create React App project, detailing the process of styling React applications using the CSS-in-JS approach offered by styled components.
Abstract
The article "Styled Components: A CSS-in-JS Approach" delves into the methodology and benefits of integrating styled components within a React application scaffolded by Create React App. It explains how styled components allow developers to write CSS directly in their JavaScript code, creating self-contained components with their styles bundled together. The author, Jennifer Fu, illustrates the step-by-step process of replacing traditional CSS files with styled components, demonstrating how to install, create, and use styled components, including handling animations and media queries. The article emphasizes the advantages of styled components, such as component independence, enhanced developer experience, and improved accessibility through features like the prefers-reduced-motion media query. It also touches on tooling and configuration, such as using babel-plugin-styled-components and babel-plugin-macros for optimizations and a better debugging experience. The conclusion advocates for the use of styled components in web development for a more streamlined and efficient styling process.
Opinions
Max Stoiber, the co-creator of styled components, expresses a preference for writing all CSS in JavaScript, avoiding the use of .css files.
The author suggests that styled components can make the debugging process easier by providing more readable class names when configured properly.
Styled components are praised for their ability to encapsulate styles within components, avoiding the need for external CSS files and potential conflicts.
The use of styled-components/macro is recommended for zero-config projects, as it simplifies the setup process and provides advanced code transpilation.
The article implies that styled components contribute to a more accessible web by facilitating the implementation of user preference-based styles, such as reducing motion for users with vestibular disorders.
The author advises against bundling styled-components with a library, suggesting it should be listed as a peer dependency to avoid version conflicts and ensure optimal tree shaking.
Styled Components: A CSS-in-JS Approach
How to adopt styled components in Create React App
It’s a CSS-in-JS approach — a JavaScript library that bundles each JavaScript component with all its belonging CSS rules and dependencies. As a result, components can run independently, without relying on any external CSS files.
Here’s is a quote from Max Stoiber, the co-creator of styled components, in February 2019:
For three years, I have styled my web apps without any .css files. Instead, I have written all the CSS in JavaScript.
Styled components are compatible with both React (for web) and React Native. We are going to use the Create React App to show how to use styled components.
Create React App With No Styles
This is what you see from Create React App — a pinning logo and some texts:
Here’s the src/App.css file, which styles the application:
What do we see if we comment out line three in the following src/App.js?:
We see Create React App without styles:
Create a Styled Component
We’re going to use Styled Components to rebuild Create React App. The first step is to install with the command npm i styled-components. styled-components becomes part of dependencies in package.json.
In src/App.css, the App-header class is styled as follows:
We need to import styled from styled-components (line three). styled is a low-level factory to create the styled.tagname helper methods. Here, a template literal is used to create a component that will render a DOM element with some styles. In this case, we create a component named AppHeader at line five. It is defined by styled, followed by a period and the element’s name, header. The detailed styles are quoted by backticks at lines 5-14.
The header tag at line 19 is replaced by the AppHeader component that we’ve just created. Make sure that styled components are capitalized so that React can recognize them as custom components.
Since AppHeader is styled by a styled component, the className is no longer needed at line 19.
We get partial styles back:
Everything is horizontally centered, the background color is set, and the text message is white.
Build More Styled Components
We continue building styled components for div and a tags:
AppDiv is created at line five, with styles at lines 5-7. AppDiv replaces div with className at line 26.
AppLink is created at line 20, with styles at lines 20-22. AppLink replaces a with className at line 32.
More things are styled:
Although the text alignment for AppDiv isn’t obvious, the blue link puts us a step closer to the original Create React App.
We’ve used styled.tagname helper methods. Can the tagname be a component name?
No. If we want to build upon a tagged template literal, styled should be used as a constructor like styled(Component). The new component inherits the styling of Component.
In the following code, Button1 is styled with the red text with white background. Button2 inherits the red text, and has the yellow background. Button3 inherits the yellow background, and is styled with the green text.
If the styled target is a simple element (styled.tagName), styled components passes through any known HTML attribute to the DOM. If it’s a custom React component (styled(Component)), styled components pass through all props.
The above button example can be accomplished by passed props used in interpolations:
It’s important to define styled components outside the render method, otherwise, they are recreated on every single render pass.
For the three generated buttons, each has two classes connected to it:
The first is the static class, which does not have any style attached to it. It’s used to quickly identify which styled component a DOM object belongs to.
The second one is the dynamic class, which is different for every element. It’s used to style the component:
Construct Animation Styled Components
In src/App.css, the App-logo class is styled as follows:
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
The @keyframes CSS at-rule controls the intermediate steps in a CSS animation sequence by defining styles for keyframes along the animation sequence.
How do we configure it to get the spinning icon back? Styled components provide a helper method to create keyframes for animations:
keyframes is imported from styled-components (line three). It’s used to define appLogoSpin at line 20. appLogoSpin is interpolated into AppLogo at line 33. Now the logo spins again!
You may wonder whether we can define media separately, similar to src/App.css. Yes, we can, with a little helper:
This little helper is css, which is imported from styled-components (line 3). It’s a helper function to generate CSS from a template literal with interpolations. media created at line 29 is interpolated into AppLogo at line 38.
Are you wondering what the media query about prefers-reduced-motion is? It’s used to detect if the user has requested the system to minimize the amount of non-essential motion. There are two accessibility choices:
no-preference indicates that the user has made no preference.
reduce indicates that the user prefers removing animation that triggers discomfort for those with vestibular motion disorders.
The following video shows that the spinning icon stops animation when Reduce motion is selected.
babel-plugin-styled-components adds support for server-side rendering, minification of styles, and a nicer debugging experience. It can be configured by .babelrc. Without explicitly setting flags to be true, default values are false.
{"plugins":[["babel-plugin-styled-components",{"ssr":false,// enable server-side rendering"displayName":false,// display component name"fileName":false// display file name"minify":false,// remove all whitespace and comments"transpileTemplateLiterals":false,// keep valuable bytes out"pure":true// remove dead code}]]}
babel-plugin-macros is quickly gaining steam as a full-featured option to allow advanced code transpilation for zero-config projects, such as the Create React App. All you need to do is to import items from the macro directory:
With both fileName and displayName set to be true, the class names in the following code are more readable, making the debug process easier:
Conclusion
Styled Components provides an improved experience for developers to write CSS in JavaScript.
If you build a library, it’s recommended that you not to bundle and ship styled-components module with a library. Make styled-components a peer dependency and mark it as external in bundler (rollup or webpack).