How to Use Multiple Layouts in Next.js
In Next.js you can wrap your pages in a component to share a common layout. But, what if you want to use many layouts?
It is possible to change the layout per page individually. In this post you will learn how to change the default layout in a page of your choice.
Using Multiple Layouts
First things first, you will need a default layout.
Create a component for shared layout.
export default function Layout({ children }) {
return (
<>
<header>Website</header>
<main>{children}</main>
<footer>© Website</footer>
</>
);
}
Here, the header
and footer
will remain the same on every page that uses this layout. The children
prop will contain the actual content of the page. You can wrap it in any HTML element you want and style according to your needs.
Now, update your _app.jsx
to use your Layout
component in all pages.
import Layout from 'src/components/Layout/Layout';
export default function MyApp({ Component, pageProps }) {
return (
<>
<Layout>
<Component {...pageProps} />
</Layout>
</>
);
}
Any page you create will be put inside your Layout
component where you placed the children
prop.
Creating Alternative Layout
Now, create another layout component that you want to use as an alternative to your default one.
export default function LayoutWithSidebar({ children }) {
return (
<>
<header>Website</header>
<main>{children}</main>
<aside>Sidebar</aside>
<footer>© Website</footer>
</>
);
}
Next, use the alternative layout in one of your pages.
import LayoutWithSidebar from 'src/components/Layout/LayoutWithSidebar';
export default function AlternativeLayoutPage() {
return <>Page with a sidebar</>;
}
AlternativeLayoutPage.getLayout = function(page) {
return <LayoutWithSidebar>{page}</LayoutWithSidebar>;
};
A couple things are happening here:
- Define a
getLayout
function on your layout component (or choose a name you want) - Next.js passes this function current page through its first parameter, in this case —
page
. - The JSX you return from this function is used as the layout for this page. This is how you can wrap the
page
in another layout —LayoutWithSidebar
.
But, this won’t be enough to override the default layout.
You need to update your _app.jsx
file to use the layout defined on a page component, if it has one.
import Layout from '../components/Layout/Layout';
export default function MyApp({ Component, pageProps }) {
const renderWithLayout =
Component.getLayout ||
function (page) {
return <Layout>{page}</Layout>;
};
return renderWithLayout(<Component {...pageProps} />);
}
Again, here’s the explanation:
- You save the component’s
getLayout
function insiderenderWithLayout
variable - If a component doesn’t have a
getLayout
function, you save a function that returns the default layout instead - Finally, you call the function saved in
renderWithLayout
to either render the page with its custom layout or the default one
Nesting Layouts
Let’s say you want to use a default layout component for the page structure and another layout for the content.
You can use composition to achieve exactly that.
import Layout from 'src/components/Layout/Layout';
import ContentLayout from 'src/components/Layout/ContentLayout';
export default function AlternativeLayoutPage() {
return <>Component wrapped in two layouts</>;
}
AlternativeLayoutPage.getLayout = function(page) {
return (
<Layout>
<ContentLayout>
{page}
</ContentLayout>
</Layout>
);
};
This way you can combine all of your layouts in any imaginable way.