How to use Material-UI with Next.js ?
Last Updated :
26 Jul, 2024
Integrating Material-UI (now known as MUI) with Next.js allows you to build modern, responsive user interfaces with a comprehensive set of React components. In this article, we will learn some additional necessary steps to be performed to integrate Material-UI with the Next.js project.
Prerequisites:
Approach
To use the Material-UI with Next.js we have to wrap the complete app with the ThemeProvider for consistent theming, using Material-UI components in your pages, and ensuring server-side rendering support with Emotion’s styling solutions for optimized performance and consistent styling.
First Let's start by creating a Next.js project.
Steps to Integrate Material UI with Next.js
Step 1: Initialize a nwe Next.js project using the following command:
npx create-next-app gfg-next-mui
Step 2: Move to the Project directory
cd gfg-next-mui
Step 3: Install Material-UI
To install the dependencies and save them in your package.json file, run:
npm install @mui/material @emotion/react @emotion/styled @emotion/server
Project Structure:
It will look like this.

The updated dependencies in the package.json file are:
"dependencies": {
"@emotion/react": "^11.13.0",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.13.0",
"@mui/material": "^5.16.5",
"next": "14.2.4",
"react": "^18",
"react-dom": "^18"
}
Step 4: Modify the _document.js file. Configure the next app for server-side rendering using the Material UI and emotion library.
JavaScript
// pages/_document.js
import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import theme from '../src/theme';
import createEmotionCache from '../src/createEmotionCache';
export default class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
<meta name="theme-color"
content={theme.palette.primary.main} />
<link rel="shortcut icon"
href="/static/favicon.ico" />
<link
rel="stylesheet"
href=
"https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
{/* Inject MUI styles first to match with the prepend: true configuration. */}
{this.props.emotionStyleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
const originalRenderPage = ctx.renderPage;
// You can consider sharing the same emotion cache between
// all the SSR requests to speed up performance.
// However, be aware that it can have global side effects.
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) =>
function EnhanceApp(props) {
return <App emotionCache={cache} {...props} />;
},
});
const initialProps = await Document.getInitialProps(ctx);
// This is important. It prevents emotion to render invalid HTML.
// See
// https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={`${style.key} ${style.ids.join(' ')}`}
key={style.key}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style.css }}
/>
));
return {
...initialProps,
emotionStyleTags,
};
};
Step 5: Define Material-UI theme with custom primary, secondary, and error colors using createTheme
from @mui/material/styles
.
Create an src folder, add theme.js and createEmotionCache.js files as below
JavaScript
// Filename - src/theme.js
import { createTheme } from "@mui/material/styles";
import { red } from "@mui/material/colors";
// Create a theme instance.
const theme = createTheme({
palette: {
primary: {
main: "#556cd6",
},
secondary: {
main: "#19857b",
},
error: {
main: red.A400,
},
},
});
export default theme;
JavaScript
// Filename - src/createEmotionCache.js
import createCache from '@emotion/cache';
export default function createEmotionCache() {
return createCache({ key: 'css', prepend: true });
}
Step 5: Update the file /pages/_app.js with the below code
JavaScript
// Filename - pages/_app.js
import * as React from "react";
import PropTypes from "prop-types";
import Head from "next/head";
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import { CacheProvider } from "@emotion/react";
import theme from "../src/theme";
import createEmotionCache from "../src/createEmotionCache";
// Client-side cache shared for the whole session
// of the user in the browser.
const clientSideEmotionCache = createEmotionCache();
export default function MyApp(props) {
const { Component,
emotionCache = clientSideEmotionCache,
pageProps } = props;
return (
<CacheProvider value={emotionCache}>
<Head>
<meta
name="viewport"
content="initial-scale=1,
width=device-width" />
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant,
consistent, and simple baseline to
build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</CacheProvider>
);
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
};
Step 6: Update the Home Component in /pages/index.js with the below code.
JavaScript
// pages/inde.js
import Head from "next/head";
import styles from "../styles/Home.module.css";
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">
Next.js!</a> integrated with{" "}
<a href="https://mui.com/">Material-UI!</a>
</h1>
<p className={styles.description}>
Get started by editing{" "}
<code className={styles.code}>
pages/index.js</code>
</p>
</main>
</div>
);
}
Steps to run the application: To run the app, type the following command in the terminal.
npm run dev
Output: