Style React Components: 7 Ways Compared



I’ve been working with a couple of developers in my office on React projects, who have varied levels of React experience. This article arose from a question one of them asked about how best to style React components.

The Various Styling Approaches

There are various ways to style React components. Choosing the right method for styling components isn’t a perfect absolute. It’s a specific decision that should serve your particular use case, personal preferences, and above all, architectural goals of the way you work. For example, I make use of notifications in React JS using Noty, and the styling should be able to handle plugins too.

Some of my goals in answering the question included covering these:

  • global namespacing
  • dependencies
  • reusability
  • scalability
  • dead-code elimination

There seems to be a number of ways of styling React components used widely in the industry for production level work:

  • inline CSS
  • normal CSS
  • CSS in JS libraries
  • CSS Modules
  • Sass & SCSS
  • Less
  • Stylable

For each method, I’ll look at the need for dependencies, the difficulty level, and whether or not the approach is really a good one or not.

Inline CSS

  • Dependencies: None
  • Difficulty: Easy
  • Approach: Worst

I don’t think anyone needs an introduction to inline CSS. This is the CSS styling sent to the element directly using the HTML or JSX. You can include a JavaScript object for CSS in React components, although there are a few restrictions such as camel casing any property names which contain a hyphen. You can style React components in two ways using JavaScript objects as shown in the example.

Example

import React from "react";

const spanStyles = 
  color: "#fff",
  borderColor: "#00f"
;

const Button = props => (
  <button style=
    color: "#fff",
    borderColor: "#00f"
  >
    <span style=spanStyles>Button Name</span>
  </button>
);

Regular CSS

  • Dependencies: None
  • Difficulty: Easy
  • Approach: Okay

Regular CSS is a common approach, arguably one step better than inline CSS. The styles can be imported to any number of pages and elements unlike inline CSS, which is applied directly to the particular element. Normal CSS has several advantages, such as native browser support (it requires no dependencies), there’s no extra tooling to learn, and there’s no danger of vendor lock in.

You can maintain any number of style sheets, and it can be easier to change or customize styles when needed. But regular CSS might be a major problem if you’re working on a bigger project with lots of people involved, especially without an agreed style guide for writing CSS.

Example

/* styles.css */

a:link 
  color: gray;

a:visited 
  color: green;

a:hover 
  color: rebeccapurple;

a:active 
  color: teal;

import React from "react";
import "styles.css";

const Footer = () => (
  <footer>
    &copy; 2020
    <a href="https://twitter.com/praveenscience">Find me on Twitter</a>
  </footer>
);

export default Footer;

More Information

You can read more about regular CSS usage of the W3C’s Learning CSS page. There are many playgrounds — such as JS Bin, JSFiddle, CodePen, and Repl.it — where you can try it out live and get the results in real time.

CSS-in-JS

CSS-in-JS is a technique which enables you to use JavaScript to style components. When this JavaScript is parsed, CSS is generated (usually as a <style> element) and attached into the DOM.

There are several benefits to this approach. For example, the generated CSS is scoped by default, meaning that changes to the styles of a component won’t affect anything else outside that component. This helps prevent stylesheets picking up bloat as time goes by; if you delete a component, you automatically delete its CSS.

Another advantage is that you can leverage the power of JavaScript to interact with the CSS. For example, you can create your own helper functions in JavaScript and use them directly in your CSS to modify the code.

Next, we’ll look at two libraries that can be used to implement this in a React app.

JSS

  • Dependencies: react-jss
  • Difficulty: Easy
  • Approach: Decent

JSS bills itself as “an authoring tool for CSS which allows you to use JavaScript to describe styles in a declarative, conflict-free and reusable way”. It’s framework agnostic, but when it comes to styling React components, React-JSS integrates JSS with React using the new Hooks API.

Example

import React from "react";
import render from "react-dom";
import injectSheet from "react-jss";

// Create your styles. Since React-JSS uses the default JSS preset,
// most plugins are available without further configuration needed.
const styles = 
  myButton: 
    color: "green",
    margin: 
      // jss-expand gives more readable syntax
      top: 5, // jss-default-unit makes this 5px
      right: 0,
      bottom: 0,
      left: "1rem"
    ,
    "& span": 
      // jss-nested applies this to a child span
      fontWeight: "bold" // jss-camel-case turns this into 'font-weight'
    
  ,
  myLabel: 
    fontStyle: "italic"
  
;

// Define the component using these styles and pass it the 'classes' prop.
const Button = ( classes, children ) => (
  <button className=classes.myButton>
    <span className=classes.myLabel>children</span>
  </button>
);

// Finally, inject the stylesheet into the component.
const StyledButton = injectSheet(styles)(Button);

const App = () => <StyledButton>Submit</StyledButton>
render(<App />, document.getElementById('root'))

More Information

You can learn more about this approach in the JSS official documentation. There’s also a way to try it out using their REPL (read-eval-print loop).

Styled-Components

  • Dependencies: styled-components
  • Difficulty: Medium
  • Approach: Decent

Styled-components is a further library that implements the above-mentioned CSS-in-JS technique. It utilizes tagged template literals — which contain actual CSS code between two backticks — to style your components. This is nice, as you can then copy/paste CSS code from another project (or anywhere else on the Web) and have things work. There’s no converting to camel case or to JS object syntax as with some other libraries.

Styled-components also removes the mapping between components and styles. As can be read in their documentation, 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 makes your code more succinct and easy to follow, as you end up working with a <Layout> component, as opposed to a <div> with a class name of “layout”.

Props can be used to style styled components in the same way that they are passed to normal React components. Props are used instead of classes in CSS and set the properties dynamically.

Example

import React from "react";
import styled,  css  from "styled-components";

const Button = styled.button`
  cursor: pointer;
  background: transparent;
  font-size: 16px;
  border-radius: 3px;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;
  transition: 0.5s all ease-out;
  $props =>
    props.primary &&
    css`
      background-color: white;
      color: green;
      border-color: green;
    `;
`;

export default Button;

More Information

Styled-components has detailed documentation, and the site also provides a live editor where you can try out the code. Get more information on styled-components at styled-components: Basics.

CSS Modules

  • Dependencies: css-loader
  • Difficulty: Tough (Uses Loader Configuration)
  • Approach: Better

If you’ve ever felt like the CSS global scope problem takes up most of your time when you have to find what a particular style does, or if getting rid of CSS files leaves you nervously wondering if you might break something somewhere else in the code base, I feel you.

CSS Modules solve this problem by making sure that all of the styles for a component are in one single place and apply only to that particular component. This certainly solves the global scope problem of CSS. Their composition feature acts as a weapon to represent shared styles between states in your application. They are similar to mixins in Sass, which makes it possible to combine multiple groups of styles.

Example

import React from "react";
import style from "./panel.css";

const Panel = () => (
  <div className=style.panelDefault>
    <div className=style.panelBody>A Basic Panel</div>
  </div>
);

export default Panel;
.panelDefault 
  border-color: #ddd;

.panelBody 
  padding: 15px;

Please note that, if you’re using Create React App, it supports CSS Modules out of the box. Otherwise, you’ll need webpack and a couple of loaders that enable webpack to bundle CSS files. Robin Wieruch has a great tutorial on this.

Continue reading
Style React Components: 7 Ways Compared
on SitePoint.

Leave a Reply

Your email address will not be published. Required fields are marked *