In Next.js, managing styles effectively is crucial for building user interfaces that are both visually appealing and maintainable. This chapter explores how Next.js supports various styling strategies, starting with global styles and then diving into the more granular approach of CSS Modules.
Global styles are styles that apply to your entire application. Think of things like resets, base typography, or site-wide layout rules. In Next.js, the conventional way to implement global styles is by importing a CSS file into your pages/_app.js (or _app.tsx) file. This file is the root component that wraps all your pages, ensuring that any styles imported here are available throughout your application.
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}Let's imagine you have a styles/globals.css file. The above code snippet demonstrates how to import it. This approach is straightforward and effective for setting up your application's foundational styles.
/* styles/globals.css */
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
line-height: 1.6;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}While global styles are powerful for broad applications, they can lead to style conflicts, especially in larger projects. This is where CSS Modules come into play, offering a scoped styling solution.
CSS Modules are CSS files where all class names and animation names are scoped locally by default. This means that a class name defined in one CSS Module file will not clash with another class name defined in a different CSS Module file, even if they have the same name. In Next.js, you can leverage CSS Modules by naming your CSS files with the .module.css extension (e.g., styles/Button.module.css).
/* components/Button.module.css */
.button {
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
}To use these locally scoped styles in your React components, you import the CSS module as an object. The class names in the CSS file become properties of this object. When you apply these classes, Next.js automatically generates unique class names to ensure scoping.
import styles from './Button.module.css';
function Button() {
return <button className={styles.button}>Click Me</button>;
}The benefit here is that the .button class from Button.module.css will not affect any other .button classes elsewhere in your application. This isolation prevents unintended style overrides and makes your component styles more predictable.
graph LR
A[App.js (or _app.js)] --> B(styles/globals.css)
C[Component.js] --> D(Component.module.css)
D --> E{Unique Class Names}
In summary, global styles are great for application-wide defaults, while CSS Modules provide a robust way to manage component-level styles, ensuring isolation and preventing naming conflicts. Next.js seamlessly integrates both, allowing you to choose the best approach for different styling needs.