This article originally appeared on Jan. 16, 2018.
Cascading Style Sheets (CSS) has been the ugly step-sister of the development world. Many developers say, “I’m a developer. I don’t care how things look.” Bottom line: Since they don’t care about how things look, they don’t care to learn CSS. They should. Developers should learn CSS to know how an application should be styled and provide responsive and accessibility support. One caveat: CSS is hard. It can take years to become proficient.
There have been many attempts over the years to improve the quirks of CSS. Out of the box, CSS doesn’t support variables (custom properties have been introduced in newer browsers), loops or functions. Pre-processors such as Sass and Less add useful features. BEM, ITCSS and SMACSS also help. However, they’re optional and can’t be enforced at the language or tooling level.
Christopher Chedeau, aka vjeux, in his famous CSS in JS talk, lists some issues with CSS. A few issues include global namespacing, styling conflicts and dead code. During the past few years, developers have been looking for ways to improve CSS modularity. React, with a focus on building component-based user interfaces, started the wave of CSS-in-JS libraries.
- Scoped styles without selectors. CSS has just one global namespace, which may cause collisions in large applications. Unique class names are created to avoid collisions.
- Avoids specificity conflicts. Two style definitions for one element can be used.
- Source order independence. No need to worry about how the order of files is imported.
- Dead code elimination. Linters will show unused components so they can be removed if not used.
- Vendor prefixing. Adds vendor prefixes only for the required browser.
- Highly expressive, which makes reading JSX easier.
There are dozens of CSS-in-JS libraries available, and more are released each week. Popular libraries include styled-components, glamorous, emotion, Radium and styled-jss. In this blog post, we’re going to review one of the more popular component-based CSS-in-JS libraries: styled-components.
Styled-components was created by Max Stoiber and Glen Maddern as a successor to CSS Modules and a new way of writing dynamic CSS for the “CSS folk.” Style-components currently has more than 150 contributors and 11,500 stars on Github. Styled-components makes components the fundamental way to build a styled user interface. It avoids potential collisions by scoping styles to the component.
What actually happens when you create a styled component and render it?
Styled-components can be installed to a project using the following commands.
For the sake of simplicity, we’ll be using StackBlitz to walk through the examples. StackBlitz is an online Visual Studio Code integrated development environment for Angular and React. See examples.
Navigate to StackBlitz and start a new project using React ES6.
- Add the styled-components library to your project. Expand Dependencies, type in styled-components and press the Enter key.
- Import styled-components by adding import styled from 'styled-components' to the top of the file.
- Add the following code above the class definition. In the code below, two styles are created. Wrapper is a section, and Title is an H1.
- Now that we have our styled-components created, it’s time to add them to the render function. Replace the render function with the following code. As you can see, using actual component names versus generic element names with classes provides a nice benefit. Styled-components will give you a more semantic component hierarchy by default.
The code below lists all code changes for this example.
Composing styles example
One of my favorite features using styled-components is the ability to compose new styles from existing components. Styled-components allows you to pass any component, not just DOM elements.
Let’s go back to StackBlitz and enhance the project.
- We want to create a new Title component that has a different color, bold font and increased font size. Copy the Title component markup and paste it below. No changes will be displayed in the output window.
- Rename the Title component to TitleBold.
- Unlike the previous styled components, we want to compose the TitleBold component from the Title component. Change styled.h1 to styled(Title).
- Update the CSS properties. Set font-size to 2.5em, font-weight to bold and color to red. Again, no changes will be displayed in the output window.
- Finally, in the render function, change Title to TitleBold. The output window will update with your new changes.
Passing properties example
Since styled-components are components, it’s possible to pass props to the styled component. This allows flexibility in using our components.
Going back to our StackBlitz project, let’s update our TitleBold and Wrapper components to support changing the background and color CSS properties based on a prop passed.
- Replace color with the following code in the TitleBold component.
- Replace background with the following code in the Wrapper component.
- If ‘primary’ is passed as a prop on Wrapper component, the background color will be set to white. If the prop is missing, the default background color will be papayawhip.
- If ‘primary’ is passed as a prop on TitleBold component, the color will be set to black. If the prop is missing, the default background color will be red.
- Below is the render function passing primary as a prop on both components. Test adding/removing the primary prop from each component.
Browser state styles example
Styled-components integrates many Sass features, such as nested rules and browser state styles (e.g., hover, active, focus). A common requirement is to change the state of a component when hovered.
- In your StackBlitz project, find the TitleBold component.
- We want to add a black text shadow with a size of 2px on the text in TitleBold.
- Update the TitleBold component to include the following hover statement.
Media query example
In the age of responsive design, it’s important for your components to be responsive. Styled-components allow you to define media templates.
- In your StackBlitz project, find the TitleBold component.
- We want to reduce the size of the text to 1.5em and set the font weight to normal if the screen’s width drops below 400px.
- Update the TitleBold component to include the following media query.
Although you can use styled-components with no tooling, there are tools available to improve the developer experience.
- Visual Studio Code — a new type of tool that combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. Code provides comprehensive editing and debugging support, an extensibility model and lightweight integration with existing tools. Atom and WebStorm also have support for CSS-in-JS and styled-components.
- stylelint — lint your styled components with stylelint
- Visual Studio support extensions — two I use for development using styled-components include:
- styled-components Ecosystem — numerous links for components, grid systems, helpers, testing and further reading articles/videos
Regardless of which CSS-in-JS library you choose, inline styling of components offers lots of great features and should be considered when building out React user interfaces. Using styled-components in your React applications will make your JSX easier to read, and your styling will become easier to manage.
You’ll also gain the power of being able to tie a component’s state directly to its styling, all from within the component itself. We covered some of the important features in this blog post. However, styled-components has much more to offer. Please review the documentation for additional information.