The best styling options for Next.js
Tags: nextjs
Published: 2022-03-29 20:27:55

Created by Vercel, Next.js is a JavaScript framework based on React. With its ability to offer [static and server rendering](https://blog.logrocket.com/ssg-vs-ssr-in-next-js/), its popularity quickly shot up amongst developers.

What's less known is that Next.js offers many ways to support CSS in your application. Whether you prefer utility CSS with its classes or prefer CSS-in-JS, Next.js has you covered. In this tutorial, you will discover a few ways to implement styling in your Next.js application. Let’s implement a styled text that turns red when the user hovers it:

![Text Highlighting](https://blog.logrocket.com/wp-content/uploads/2022/03/text-highlighting.gif)

## Using global CSS styling in Next.js

The easiest way to write CSS in a Next.js application [is through its global stylesheet](https://github.com/mariesta/nextjs-styling-options/tree/main/with-global-css)). Every newly created Next.js project comes with a `styles` folder and inside it, a `global.css` stylesheet.

As a result, you can start writing CSS right away with no setup required. For example, in `styles/global.css`, you can add this:

```css
    .paragraph {
      font-size: 16px;
      text-align: center;
    }

    .paragraph:hover {
      color: red;
    }
```

The styles created in `global.css` will then apply to your entire application.

To do so, this stylesheet can only be imported in `_app.js,` as the `App` component initializes all the pages in your Next.js pages.

In a new Next.js project, it is done for you, but if you don't already have an `_app.js` file in your `pages` folder, create one. Once done, import your new global stylesheet:

```css
//In _app.js, import your global stylesheets
    import '../styles/globals.css'

    function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />
    }

    export default MyApp
```

You can then use those classes in your application. For example, on your homepage in `pages/index.js`:

```css
    export default function Home() {
      return (
        <p className="paragraph">I am styled with a global css stylesheet</p>
      )
    }
```

### Pros to using global styling in CSS

*   No setup required
*   Perfect for small projects like POC

### Cons

*   All styling is contained in a single file
*   It’s difficult to scale as your project grows

## Using CSS modules with Next.js

As convenient as a global stylesheet can be when just starting, this file can become less manageable as your application grows.

Also, Next.js is a component-based framework, meaning it is easier to split styling for respective components. For instance, if you have a component for your footer, it would be easier to import a stylesheet containing the styling of this component, but nothing more. Enter CSS modules!

If you are not familiar, [CSS modules allow you to isolate your CSS by creating files for style-specific components](https://github.com/mariesta/nextjs-styling-options/tree/main/with-css-modules). They are very easy to use, as they are simple CSS but have the `module.css` extension instead. Like the previous method, it requires no setup and can be used in addition to a global stylesheet.

Here is an example of a `Home.module.css`:

```css
    //Home.module.css
    .paragraph {
      font-size: 16px;
      text-align: center;
    }

    .paragraph:hover {
      color: red;
    }
```

In your component, `pages/index.js`, you can then import your stylesheet and use it:

```css
  import styles from '../styles/Home.module.css'
   export default function Home() {
      return (
        <p className={styles.paragraph}>I am styled with CSS modules</p>
      )
    }
```

### Pros to using CSS modules for styling

*   No setup required
*   Components can split styling
*   Can be used with global styling
*   Unlike global styling, conflicts between classes are avoided

### Cons

*   No dynamic styling (e.g., based on a status like loading, error, success, etc.)

## Next.js styling with Sass

If basic CSS is not enough and you find yourself in search of a CSS framework, look no further than Sass. Describing itself as "[CSS with superpowers](https://sass-lang.com/)", it is a popular framework compatible with CSS and offers lots of cool features like variables, nesting, and mix-ins. [Here’s a GitHub repo for our example project](https://github.com/mariesta/nextjs-styling-options/tree/main/with-sass).

Using Sass with Next.js is straightforward. All you have to do is install the library:

```css
   npm install sass
    # or
    yarn add sass
```

Once done, you can start writing Sass code. Don't forget the `.scss` or `.sass` file extensions! Here is an example of Sass code in `styles/Home.module.scss`:

```css
    //Home.module.scss
    $hover-color: red;

    .paragraph {
      font-size: 16px;
      text-align: center;
    }

    .paragraph:hover {
      color: $hover-color;
    }
```

Similar to using CSS modules, we’ll import the new file to style our application once we finish writing our CSS.

```css
  import styles from '../styles/Home.module.scss'
    export default function Home() {
      return (
        <p className={styles.paragraph}>I am styled with SASS</p>
      )
    }
```

Pros:

*   Easy setup with Next.js
*   CSS compatible
*   Interesting features for complex styling needs like variables, nesting, etc.

Cons:

*   Time lost learning new functionalities of SASS

## `More complex than CSS` Styling with Styled-JSX

The previous three methods covered the best styling options if you prefer Utility CSS. But perhaps you are more of a CSS-in-JS kind of person. In which case, [Styled-JSX](https://github.com/vercel/styled-jsx) might be up your alley.

Built by Vercel, the founder of Next.js, Styled-JSX allows developers to write CSS in their JavaScript code. There is no setup necessary, and it works out of the box.

[Here is an example of Styled-JSX](https://github.com/mariesta/nextjs-styling-options/tree/main/with-styled-jsx):

```css
    export default function Home() {
      return (
        <div className="paragraph">
          <style jsx>{`
            .paragraph {
              font-size: 16px;
              text-align: center;
            }

            .paragraph:hover {
              color: red;
            }
          `}</style>
          <p>I am a component styled with Styled-JSX</p>
        </div>
      )
    }
```

### Pros to using Sass with Next.js

*   No setup required
*   Dynamic styling
*   Portability: your code (CSS and JS) is contained in one file and can therefore be moved easily

### Cons

*   Not as much support as other CSS-in-JS libraries (7k stars on Github vs. 36k for styled-components)
*   Code readability can be more difficult when mixing CSS and JS

## Using styled-components

Styled-JSX can be convenient to start with, but hard to debug as your application grows. As a result, you might be tempted by [styled-components](https://blog.logrocket.com/8-awesome-features-of-styled-components/).

Styled-components is very practical, as it was created for React. It allows developers to create components with style automatically injected. You can also make use of props for dynamic styling (i.e., for disabled or hover state). Check out a sample project [here](https://github.com/mariesta/nextjs-styling-options/tree/main/with-styled-components).

To use it in Next.js, start by installing the library:

```css
    npm i styled-components
    # or
    yarn add styled-components
```

The only drawback of using styled-components is that it was made for React, meaning it’s geared for client-side rendering. At the moment, server-side rendering is not supported out of the box.

However, this is easily fixed by creating a new `pages/_document.js` file and adding this:

```css
 import Document, { Head, Html, Main, NextScript } from 'next/document'
    import { ServerStyleSheet } from 'styled-components'

    export default class MyDocument extends Document {
      render() {
        return (
          <Html lang="en">
            <Head></Head>
            <body>
              <Main />
              <NextScript />
            </body>
          </Html>
        )
      }

      static async getInitialProps(ctx) {
        const sheet = new ServerStyleSheet()
        const originalRenderPage = ctx.renderPage

        try {
          ctx.renderPage = () =>
            originalRenderPage({
              enhanceApp: (App) => (props) =>
                sheet.collectStyles(<App {...props} />),
            })

          const initialProps = await Document.getInitialProps(ctx)
          return {
            ...initialProps,
            styles: (
              <>
                {initialProps.styles}
                {sheet.getStyleElement()}
              </>
            ),
          }
        } finally {
          sheet.seal()
        }
      }
    }
```

Once done, you can import the library into your components and start using it. For example, in `pages/index.js`, you can create a `Paragraph` styled component for your homepage:

```css
 import styled from 'styled-components'
    const Paragraph = styled.p`
      font-size: 16px;
      text-align: center;

      &:hover {
        color: ${props => props.hoverColor};
      }
    `

    export default function Home() {
      return <Paragraph hoverColor="red">I am a component made with Styled Components</Paragraph>
    }
```

### Pros of using styled-components with Next.js

*   Built using React in mind and has lots of community support
*   Dynamic styling based on props
*   Customizable and reusable like React components (i.e., `<Title />` instead of `<h2 className="title"/>`)

### Cons

*   Additional configuration necessary for server-side rendering frameworks like Next.js
*   Bit of a learning curve getting used to the functionalities
*   When compiled, styled-components classes become random (i.e., `css-1kybr8i`), making debugging harder

## Emotion

Another CSS framework created with React in mind is [Emotion](https://emotion.sh/docs/introduction). It offers a CSS prop (to pass style directly to an element) and styled components. An additional benefit of Emotion is that server-side rendering works out of the box. [Check out GitHub here](https://github.com/mariesta/nextjs-styling-options/tree/main/with-emotion).

To use Emotion in your Next.js application, you first need to install the library:

```css    
    npm install --save @emotion/react
    #or
    yarn add @emotion/react
```

To use styled components, you should also install the required library:

```css
    npm install --save @emotion/styled
    # or
    yarn add @emotion/styled
```

Then, you can start writing your styled components directly. In `pages/index.js`, here is an example of a `Paragraph` component:

```css
    import styled from '@emotion/styled'

    const Paragraph = styled.p`
      font-size: 16px;
      text-align: center;

      &:hover {
        color: ${props => props.hoverColor};
      }
    `

    export default function Home() {
      return <Paragraph hoverColor="red">I am a component made with Emotion (Styled Components)</Paragraph>
    }
```

### Pros to using Emotion

*   Server-side support and easy setup with Next.js
*   With @emotion/styled, you get all the advantages of styled components
*   Many packages for different needs: CSS, styled, Jest, native, etc.

### Cons

*   Like styled-components, Emotion generates random class names, making debugging with the element inspector harder
*   A bit of learning curve getting used to the functionalities

## Styling Next.js with Tailwind CSS

Using PostCSS, Next.js also offers support to popular tools such as Tailwind CSS. [By installing Tailwind as a PostCSS plugin](https://github.com/mariesta/nextjs-styling-options/tree/main/with-tailwind-css), it will scan your code and generate the correct stylesheets for you. Not only is it fast, but it also comes with a list of utility classes for you to choose from (i.e., spacing, text size, and more).

To use it with Next.js, start with installing `tailwindcss`, `postcss`, and `autoprefixer` as peer dependencies:

```css
    npm install -D tailwindcss postcss autoprefixer
```

Run `tailwindcss` init to generate the required files:

```css
    npx tailwindcss init -p
```

This command generated two files:

*   `postcss.config.js,` which you don't need to touch

*   `tailwind.config.js`

In the latter, add your template paths. These configs will tell Tailwind CSS what code to scan to generate the stylesheet:

```css
    module.exports = {
      content: [
        "./pages/**/*.{js,ts,jsx,tsx}",
        "./components/**/*.{js,ts,jsx,tsx}",
      ],
      theme: {
        extend: {},
      },
      plugins: [],
    }
```

In `styles/global.css`, add the Tailwind CSS directives:

```css
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
```

If you are using a newly created Next.js project, this will be done for you, but, if not, make sure that `pages/_app.js` imports your `styles/global.css` stylesheet:

```css
    import '../styles/globals.css'

    function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />
    }

    export default MyApp
```

You can now start using Tailwind CSS. In `pages/index.js`, if you want to create a centered paragraph with a hover state, you can do so like this:

```css
    export default function Home() {
      return (
        <p class="text-center text-lg hover:text-red-600">
          I am a component made with Tailwind CSS
        </p>
      )
    }
```

### Pros to using Tailwind CSS

*   Lots of pre-defined classes whether for padding, margin, color, and more
*   Once familiar with the classes, the styling process becomes faster
*   Compiled CSS is automatically optimized by removing unused CSS

### Cons

*   No separation of content vs. structure because CSS and HTML are combined
*   Time needed to learn all the different classes

## Conclusion

Choosing a styling option depends on many factors: the size of your project, time, and, mostly, personal preferences. Thankfully, whether you prefer utility CSS or CSS-in-JS, Next.js offers built-in support for CSS.

In this tutorial, you discovered some of those. First, you learned how to write CSS with global stylesheets or CSS modules. For developers with more complex needs, you also saw how to use Sass with Next.js.

Then, for those who prefer CSS-in-JS, we covered some methods such as Styled-JSX, styled-components, and Emotion.

Finally, you also learned that Next.js offers support for tools such as Tailwind CSS with PostCSS, which benefits developers who want access to a design system with thousands of pre-built CSS classes. Thanks for reading!

---

## [LogRocket](https://logrocket.com/signup): Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try [LogRocket](https://logrocket.com/signup). 

![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)

[LogRocket](https://logrocket.com/signup) is like a DVR for web and mobile apps, recording literally everything that happens on your Next app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — [start monitoring for free](https://logrocket.com/signup).