Styling React Apps With CSS: Your Ultimate Guide.

Styling React Apps With CSS: Your Ultimate Guide.

Introduction

It is no longer news that React is one of the most powerful and used Javascript frameworks. It is built on a style of programming known as Declarative Programming, where you need to 'declare' what you want to do and React will handle all the how-to i.e details. But React is not just all about composing components and making sure your logics work, it is also about styling and making sure your app looks good, nobody wants an ugly UI.

In this article, you will learn the major ways you can style your React apps using CSS, The best practices in styling React apps, How to conditionally render styles in React and a lot more.


Prerequisite

You must have a basic understanding of React, Javascript and CSS before you dive into this article to fully understand the contents, nevertheless, I've simplified the concepts in this article so you can understand everything perfectly.


Ways to Use CSS in React Apps

There are several ways to use the Cascading Style Sheet(CSS) in your React apps, In this section, you learn the four(4) most common and efficient ways to do it. They are;

  1. Inline CSS

  2. External CSS

  3. Styled Components

  4. CSS Modules

Inline CSS

This is when CSS styles are written in the React JSX codes, it is used to apply CSS styles to a single HTML element in the DOM. It is important to mention that the Inline CSS takes the most priority and as a result overrides all other forms of styling applied to the same HTML element.

To use Inline CSS, the style attribute is used just before the closing tag of the target HTML element in the JSX code. This attribute takes a javascript object as its value, the keys in this object are CSS property names written in camelCase e.g backgroundColor, as opposed to the kebab case- hyphens(-)-used in CSS sheets and their values, are the CSS styles being applied. Illustrations of this are given in the code snippets below:

function MyReactComponent(){

return <button style={{ backgroundColor: 'red', borderRadius: 10, padding: 20 }}> 
Inline CSS example</button>

}

In the above code snippet, the style attribute has been used to attach an inline style to the button element, you should take note of how the CSS property names have been written in camelCase and not the kebab case used in CSS sheets. Also worthy of note is the absence of units in the borderRadius and padding values, this is general for numeric inline style properties with a "px" unit; If you'd like to use other units like "em" "rem" etc. the values are written as strings, an illustration is given below;

function MyComponent(){

return <div style={{ color: 'blue', margin: "10rem", padding:"2em",   boxShadow: '1px 2px 9px #F4AAB9' }}> Inline Styled Component</div>

}
export default MyComponent

Also, an alternative way to write Inline styles is to create a javascript object with styling information and pass it into the style attribute as shown below:

function App(){

 const titleStyle = {
      color: "red",
      backgroundColor: "black",
      padding: 20,
      fontFamily: "serif"
    };

 return (
      <div>
      <h1 style={titleStyle}>Inline CSS</h1>
      <p>Let's style our React App!</p>
      </div>
    );
}

export default App

A further example of Inline CSS

const App = () => {
  return (
    <div>
      <div
        style={{
          boxShadow: '1px 2px 9px #F4AAB9',
          margin: '4em',
          padding: '1em',
        }}
      >
        Hello World
      </div>
    </div>
  )
}

export default App

One major flaw that is seen with Inline CSS is that it makes your React components bulky and often difficult to debug. Also, it leads to excessive code repetition which you typically want to avoid when programming.

External CSS

This is done by creating a new CSS file in your project directory using the .css extension and then adding your regular CSS inside the file, after which you import the file into your React component. An example of this is given below:

  • The CSS styles in a file dir .style.css

      .container {
        text-align: center;
        border: 1px;
        box-shadow: '1px 2px 9px #F4AAB9';
        margin: 4em;
        padding: 1em;
    
       }
    
      .title {
        text-align: center;
        color: red;
      }
    
      p {
        color: yellow;
       }
    
  • The React Component named App.js

      import React from 'react';
      import ".style.css";
    
      function App(){
    
      return (
            <div className="container">
            <h1 className="title">Inline CSS</h1>
            <p>Let's style our React App!</p>
            </div>
          ); 
    
      }
    
      export default App
    

    Importing the stylesheet into the React component App.js applies the styles to the HTML elements. The problem with this way of styling our React app is that the CSS styles are not scoped to the components they are imported to and as a result, they become globally available. This can lead to styling problems especially when you have multiple developers working on the same project and they use the same className for their elements.

Styled Components

This is a third-party library used to build components that have certain styles attached to them and these styles do not affect elements outside such components. The styled-components are a CSS-in-JS tool that enables the coupling of React components and their CSS styles in the same file, behind the scenes this library attaches unique classNames to HTML elements so you do not need to worry about classNames conflicts as in External CSS.

The styled components have certain advantages over other ways of styling React Apps, these are;

  • Dynamic Styles: With Styled components, It is easier to create dynamic styles and render styles conditionally in your React App.

  • JS and CSS in the Same File: With the styled component it is possible to write your CSS in your React Components without bloating your components as in Inline CSS. This makes it even easier to render styles conditionally by passing state management props.

  • Vendor Automatic Prefixing: Vendor names like ms, moz, webkit etc do not need to be used in CSS property names as the Styled Component library does this for you behind the scenes.

  • Easy Maintenance and Debugging: styled-components are easy to debug and maintain, especially since style changes only affect components that import them i.e the styles are scoped only to components that import them.

Step by Step Guide on how to use Styled Components

  • Install the library on your project using your terminal:

      npm install --save styled-components
    
  • Import styled from styled-component in your React Component file:

      import React from 'react';
    
      import styled from 'styled-components'
    
  • Now you are ready to create your first styled component. Create a new variable, the name is totally up to you.

      import React from 'react';
      import styled from 'styled-components'
    
      const MyButton= styled.button``
    

    The Imported styled object contains all the HTML elements as methods. In this example, we have called a button method which will return an HTML element-a button-that can then be stored in the MyButton component and used anywhere in the code. Also, there is a strange syntax in the code snippet above, the two backticks (``), you've probably never seen it before; this is known as a Tagged Template literal. It is a regular javascript syntax that has been incorporated by the styled component library

  • Next, you can then begin to add your regular CSS styles between the two backticks.

    
      import React from 'react';
      import styled from 'styled-components'
    
      const MyButton= styled.button`
        background: transparent;
        border-radius: 3px;
        border: 2px solid palevioletred;
        color: palevioletred;
        margin: 0.5em 1em;
        padding: 0.25em 1em;
        &:focus:{
          background-color: red;   
         }
    
        @media (min-width:789px){
          width: auto; 
         }
      `
    

    And there you have it, you've created your first styled component. Notice how d CSS selectors were omitted in the styling and how & is used to replace the selector that should have been before the focus pseudo-selector? This is because the styled component library adds the right selectors behind the scene.

  • After you've successfully added styles, all that is left is to use the styled component in your component

      import React from 'react';
      import styled from 'styled-components'
    
      const MyButton= styled.button`
        width: 100%
        background: transparent;
        border-radius: 3px;
        border: 2px solid palevioletred;
        color: palevioletred;
        margin: 0.5em 1em;
        padding: 0.25em 1em;
    
        &:focus:{
          background-color: red;   
         }
    
        @media (min-width:789px){
          width: auto; 
         }
      `
      function App() {
    
      return (
           <div>
               <p> Style Components is awesome!</p>
               <MyButton>Yes</MyButton>
           </div>
        )
    
      }
    
      export default App;
    

CSS Modules

CSS modules are CSS files In which all the classNames and CSS selectors are scoped locally and can only be available in another file when they are imported. The classes and selectors act like local variables in Javascript, with these modules you can have elements with similar class names in your program without having to worry about styling conflicts. Behind the scenes, CSS classes in the modules are given unique ClassNames, you'll see this when you inspect the DOM on your chrome developer tools.

If you enjoy having your CSS and javascript codes separated in different files without the risk of style conflicts as in the external CSS, then the CSS styling module is the one for you. One advantage of the CSS modules is that it ships with React projects created with create-react-app and create-vite so you do not need to install it separately.

Step by Step Guide on how to use CSS Modules.

  • Create a new CSS file with the .module.css extension e.g style.module.css

  • Next, using the Named import syntax, you import your CSS file into the React component you want to style

      import React from 'react';
      import styles from '/style.module.css';
    

    After importing the CSS module into your Component as in the above code snippet, you then get access to the javascript object styles that contain all the classes present in your CSS module.

  • Add your CSS styles into your .module.css file:

      .container {
        text-align: center;
        border: 1px;
        box-shadow: '1px 2px 9px #F4AAB9';
        margin: 4em;
        padding: 1em;
    
       }
    
      .header {
        text-align: center;
        color: red;
      }
    
      .text {
        color: yellow;
       }
    
  • Finally, you can style your JSX tags by setting the className prop value to be style.(your_css_class)

      import React from 'react'
      import styles from '/style.module.css';
    
      function App(){
    
      return (
            <div className={styles.container}>
            <h1 className={styles.header}>CSS Modules </h1>
            <span className={styles.text}>Hello World</span>
            </div>
          ); 
    
      }
    
      export default App
    

Conditional/Dynamic Styling

So far you've learned several ways to style your React App using static CSS. In this section, you'll learn how to add Conditional or Dynamic styles. Conditional styles are styles that are rendered only when a particular condition is true e.g when a user submits an empty form, you may want to notify them this Is not allowed by changing the color of the input field or you may want to notify the user a particular task is successful by changing the position of an HTML element. All of these and more are possible with the Dynamic Rendering feature on React.

Conditional Styling Using Inline CSS

The code snippet below shows step by step guide to rendering styles conditionally using Inline CSS.

  • In this example, the background-color of a submit button is set to change upon successful form submission. First, we have a form-handling component with all the logic to handle and submit a form

      import React from 'react'
      import { useState } from 'React'
    
      function FormHandler(){
    
      const [userName,setUserName]=useState()
    
      const onChangeHandler=(event)=>{
        //This even listerner listens to changes in the input field
         setUserName(event.target.value)//this sets the state "userName
      }
    
      const submitHandler=(event)=>{
         //This event listener handles form submission
          event.preventDefault()//this prevents the default submit behaviour
         //Code to add Conditional styles will be written here
      }
    
      return (
            <div>
            <label>Your name:</h1>
            <input onChange={onChangeHandler}/>
            <button style={{ backgroundColor: 'green', borderRadius: 10, padding: 4 }} onSubmit={submitHandler}>Submit</button>
            </div>
          ); 
    
      }
    
  • In the code snippet below logic to change the button color from red to green upon valid submission has been added in the submitHandler.You'll notice also that the inline styling on the button element has also been updated to conditionally render a red-colored button when isValid is false and a green-colored one when true.

    
      import React from "react"
      import {useState} from "React"
    
      function FormHandler(){
    
      const [isClicked,setIsClicked]= useState(false)
      const [userName,setUserName]=useState("")
    
      const changeHandler=(event)=>{
      setUserName(event.target.value)
      }
      const submitHandler=(event)=>{
      event.preventDefault()
      if(userName.trim() !==""){
      setIsClicked((prev)=>!prev)
        }
      }
    
      return(
       <div>
            <label>Your name:</h1>
            <input onChange={onChangeHandler}/>
            <button style= {{ backgroundColor: `${isClicked? "green" : "red"}`, borderRadius: 10, padding: 4 }} onSubmit={submitHandler}>Submit</button>
            </div>
      )
      }
    

Conditional Styling Using External CSS

Conditional styling can also be used with the External CSS In a similar way it has been applied to the Inline CSS. The Code snippets below show step by step guide to achieving this.

  • In this Illustration, the functionality to change the color of the <h1> HTML element upon button click will be implemented.

  • First, prepare an external CSS file with your styles in it.

      .header{
        color:  yellow;
        text-align: center;
      }
    
      .header clicked{
       color: green;
      }
    
      button{
        background: transparent;
        border-radius: 3px;
        border: 2px solid palevioletred;
        color: palevioletred;
        margin: 0.5em 5em;
        padding: 0.25em 1em;
      }
    
  • Import the style.css file into the React Component

      import React from 'react'
      import { useState } from 'React'
      import "./style.css"
    
      function App (){
    
      return(
         <div>
             <h1 className="header">Hello World!</h1>
             <button>click me</button> 
         </div>
        )
      }
    
      export default App
    
  • Add the logic to change the color of the h1 tag using the state management hook- useState and External CSS.

      import React from 'react'
      import { useState } from 'React'
      import "./style.css"
    
      function App (){
      const [isClicked,setIsClicked]=useState(false)
    
      const clickHandler=()=>{
       setIsClicked((prev)=> !prev) //sets the value of the isClicked to the opposite of the prev value.
       }
    
      return(
         <div>
             <h1 className={`header ${isClicked && "clicked"}`}>Hello World!</h1>
             <button onClick={clickHandler}>click Me</button>
         </div>
        )
      }
    
      export default App
    

    In the code snippet above, when the value of isClicked becomes true the new clicked CSS style will be added to change the color of the hi tag to green.

Conditional Styling With Styled Components

It's relatively easy to render styles conditionally when using the styled components. The ability to write CSS in JS in this tool enables developers to use React props in their CSS styles, this makes Conditional styling and rendering even easier.

The code snippets below show how conditional styling can be used in styled components to change the border-color of a button on hover.

  • Set up a React component using the style component to style its element

      import React from 'react';
      import styled from 'styled-components'
      import { useState } from 'React'
    
      const Button= styled.button`
        width: 100%
        background: transparent
        border-radius: 3px;
        border: 2px solid ${props=> (props.hover ? "gold" : "palevioletred")}; 
        color: palevioletred;
        margin: 0.5em 1em;
        padding: 0.25em 1em;
    
        &:focus:{
          background-color: red;   
         }
      `
      function App() {
       const [ishovered, setHovered]=useState(false)
    
       const hoverHandler=()=>{
       setHovered((prev)=> !prev)
      }
    
      return (
           <div>
               <p> Style Components is awesome!</p>
               <Button hover={isHovered} onMouseEnter={hoverHandler}>Yes</Button>
           </div>
        )
    
      }
    
      export default App;
    

    In the code snippet above, a ternary operator has been used to conditional change the border-color of the button using the hover prop as a condition.

Conditional Styling with CSS Modules

The CSS modules also support the conditional rendering of CSS styles. This is illustrated in the code snippets below.

  • In this illustration, conditional styling is used to highlight the <span> element upon click. First, set up a React Component using a CSS style.module.css file.

      .container {
        text-align: center;
        border: 1px;
        box-shadow: '1px 2px 9px #F4AAB9';
        margin: 4em;
        padding: 1em;
    
       }
    
      .hello-header {
        text-align: center;
        color: red;
      }
    
      .text {
        color: yellow;
       }
      .text highlight {
          background-color: yellow;
      }
    
      import React from 'react'
      import { useState } from 'React'
      import style from "./style.module.css"
    
      function App (){
      //The on click logic will be added here
    
      return(
         <div className={style.container}>
             <h1 className={style["hello-header"]}>Hello World!</h1>
             <span className={style.text}>click me</span> 
         </div>
        )
      }
    
      export default App
    
  • Adding Logic to highlight the span upon click.

      import React from 'react'
      import { useState } from 'React'
      import style from "./style.module.css"
    
      function App (){
      const [isHightlighed,setIsHighlighted]=useState(false)
    
      const clickHandler=()=>{
         setIsHighlighted((prev)=> !prev)
      }
    
      return(
         <div className={style.container}>
             <h1 className={style["hello-header"]}>Hello World!</h1>
             <span  className={`${style.text} ${isHighlighted ? "highlight" : " "}`} onClick={clickHandler}>click me</span> 
         </div>
        )
      }
    
      export default App
    

From the code snippets you've seen so far in this section, it is quite obvious that dynamic rendering of CSS styles involves the addition or removal of className using the state management hook-useState.


Conclusion

In this article, you've learned several ways you can style your React apps with CSS and also how to render style conditionally using each of these tools.

In reality, the styling tool you will use for your React Apps completely depends on which one of these tools you're most comfortable with, they are all powerful and capable tools for styling all React Apps. I use the CSS modules in most of my React projects because I like to separate my CSS from JS code and I also hate to worry about class names while styling my Apps. For me, the CSS modules offer the best of both worlds. You can access the styled components docs here.

It's a wrap, I hope you enjoyed reading this piece as much as I enjoyed writing it, drop a like and comment below. Until next time, folks.