Styling Next.js components using CSS
By Flavio Copes
Learn how to style Next.js components with built-in CSS and Sass support, CSS Modules, and styled-jsx scoped styles, without the old Zeit CSS plugins.
How do we style React components in Next.js?
We have a lot of freedom, because we can use whatever library we prefer.
When I wrote this post in 2019, importing a plain .css file needed a plugin. That’s long gone: since Next.js 9.2 global CSS and CSS Modules work out of the box, and Sass too once you install the sass package. I cover those at the end.
Next.js also ships with styled-jsx, a library built by the same people working on Next.js, and that’s what this post is about. It gives us scoped CSS, which is great for maintainability because the CSS only affects the component it’s applied to.
I think this is a great approach at writing CSS, without the need to apply additional libraries or preprocessors that add complexity.
One thing to know before you start: styled-jsx works out of the box in the Pages Router, the pages/ folder used in this tutorial. In the App Router it only runs in Client Components (files starting with 'use client'), and you need to set up a style registry first, as the Next.js CSS-in-JS guide shows. Next.js 16 still bundles it, so nothing to install.
To add CSS to a React component in Next.js we insert it inside a snippet in the JSX, which start with
<style jsx>{`
and ends with
`}</style>
Inside this weird blocks we write plain CSS, as we’d do in a .css file:
<style jsx>{`
h1 {
font-size: 3rem;
}
`}</style>
You write it inside the JSX, like this:
const Index = () => (
<div>
<h1>Home page</h1>
<style jsx>{`
h1 {
font-size: 3rem;
}
`}</style>
</div>
)
export default Index
Inside the block we can use interpolation to dynamically change the values. For example here we assume a size prop is being passed by the parent component, and we use it in the styled-jsx block:
const Index = props => (
<div>
<h1>Home page</h1>
<style jsx>{`
h1 {
font-size: ${props.size}rem;
}
`}</style>
</div>
)
If you want to apply some CSS globally, not scoped to a component, you add the global keyword to the style tag:
<style jsx global>{`
body {
margin: 0;
}
`}</style>
Plain CSS files, CSS Modules and Sass
If you’d rather keep your CSS in .css files, Next.js handles that with no configuration.
For a global stylesheet, import it once from pages/_app.js in the Pages Router (that’s the only file allowed to import global CSS there), or from the root app/layout.js in the App Router:
import '../styles/globals.css'
For styles scoped to one component, use CSS Modules. Name a file Button.module.css, import it, and use the class names as an object:
import styles from './Button.module.css'
export default function Button() {
return <button className={styles.primary}>Save</button>
}
For Sass, run npm install sass and import a .scss or .sass file the same way, including Button.module.scss for a scoped module.
If you find @zeit/next-css or @zeit/next-sass in an old tutorial (the original version of this post used them), skip them. Both packages are marked deprecated on npm, pointing at the built-in support that replaced them.
If you prefer a CSS-in-JS library, Styled Components is another common option, with the same Client Components caveat as styled-jsx in the App Router.
Want me to talk about your product? You can sponsor this site.
Related posts about next: