The key to easily adding transitions for the pages in the app folder of NextJs 13 is using the template files, instead of layouts. Let's see how we can do this.
In this tutorial we will build the below enter page animation example:
The NextJs app folder setup
We will start with a very simple app folder structure. Just two basic pages with some static content:
/app
/news
page.js -> news page
page.js -> main dashboard page
Both pages have content similar to the one below:
export default function Page() {
return <>
<h1>title here</h1>
<p>
content here
</p>
</>
}
The CSS setup for the animations
The animation will be done with pure old CSS animations.
The styling for our small site is handled by two files:
-
the
global.css
file that will contain the general styling for the body element and the links:body { margin: 0; height:100vh; background-color: orangered; color: white; padding: 1rem; } body a { color: white; display: inline-block; margin: 0.5rem; }
-
the
utils.module.css
module that will contain the CSS classes needed for the animations:.content { height: 100%; } .page { transition: 2s; height: 100%; opacity: 0; } .fadeIn { opacity: 1; }
Using NextJs templates to show enter page animations
The actual animation will be done by having the page opacity transition from 0 (the value set by the .page
class) to 1 (the value set by the .fadeIn
class).
At each page entry, we will need to add the .fadeIn
class after the page was loaded.
The template files are very similar to layouts. The difference is that a NextJs template is fully remounted for each page load. Therefore the useEffect
hook will get called each time a user enters a page, so this will make a perfect place to add the .fadeIn
class that will trigger the animation:
"use client"
import Link from "next/link";
import { useState, useEffect } from "react";
import styles from "./utils.module.css";
export default function RootTemplate({ children }) {
const [transitionStage, setTransitionStage] = useState("fadeOut");
useEffect(() => setTransitionStage("fadeIn"), []);
return (
<div className={`${styles.content}`}>
<nav>
<Link href="/">🗃 Dashboard</Link>
<Link href="/news">📰 News</Link>
</nav>
<div className={`${styles.page} ${styles[transitionStage]}`}>
{children}
</div>
</div>
);
}
Remember that we will need to mark the template component as a client component in order to use the React client hooks.
Note that the template also contains navigation links that allow us to move from one page to another. If you are curious I've written also about how to highlight the active link in a NextJs navigation menu.
You can see the full code of this example here.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
📖 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.