Edit on StackBlitz
"use client";
import { useEffect } from "react";
import { SizeWatcher } from "lisn.js";
import { PagerComponent, PagerPageComponent } from "@lisn.js/react";
import "lisn.js/pager.css";
import Image from "next/image";
import styles from "./demo.module.css";
export default function Page() {
// Track the size of the pager (or equivalently, and for simplicity, in this
// case, we'll track the window size since the pager is full screen), so that
// we can calculate transforms for several elements.
useEffect(() => {
const watcher = SizeWatcher.reuse();
watcher.trackSize(null, { threshold: 0 });
return () => {
// cleanup
watcher.noTrackSize();
};
}, []);
return (
<>
<div className={[styles.wrapper, "light-theme"].join(" ")}>
<PagerComponent className={styles.demo} config={{ fullscreen: true }}>
{/* https://www.pexels.com/photo/yellow-black-and-purple-colored-papers-2457284/ */}
<PagerPageComponent className={styles.page} data-slide="intro">
<h1>Scroll down (or swipe/drag up)</h1>
</PagerPageComponent>
<PagerPageComponent className={styles.page} data-slide="think">
<Image
className={styles.background}
src="/images/pager-think.png"
alt=""
/>
<h1>Think</h1>
</PagerPageComponent>
<PagerPageComponent className={styles.page} data-slide="outside">
<Image
className={styles.background}
src="/images/pager-outside.png"
alt=""
/>
<h1>Outside</h1>
</PagerPageComponent>
<PagerPageComponent className={styles.page} data-slide="the">
<Image
className={styles.background}
src="/images/pager-the.png"
alt=""
/>
<h1>The</h1>
</PagerPageComponent>
<PagerPageComponent className={styles.page} data-slide="page">
<Image
className={styles.background}
src="/images/pager-page.png"
alt=""
/>
<h1>Page.</h1>
</PagerPageComponent>
</PagerComponent>
</div>
</>
);
}
/* Container */
.wrapper {
--animate-duration: 0.4s;
background: var(--bg-color);
position: fixed;
top: 0;
left: 0;
width: 100vw;
width: 100dvw;
height: 100vh;
height: 100dvh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
}
/* Individual pages */
.background {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.page[data-slide] {
transition-property: opacity, transform;
box-shadow: none;
opacity: 1;
}
.page[data-slide][data-lisn-page-state="next"] {
opacity: 0;
}
.page[data-slide="think"] {
z-index: 4;
}
.page[data-slide="think"][data-lisn-page-state="next"] {
transform: translate3d(0px, calc(-100% - 10px), 0px);
}
.page[data-slide="outside"] {
z-index: 3;
}
.page[data-slide="the"] {
z-index: 2;
}
.page[data-slide="the"][data-lisn-page-state="next"] {
transform: translate3d(calc(-100% - 10px), calc(-100% - 10px), 0px);
}
.page[data-slide="page"] {
z-index: 1;
}
.page[data-slide="page"][data-lisn-page-state="next"] {
transform: translate3d(calc(100% + 10px), 0px, 0px);
}
/* Page content */
.page[data-slide] h1 {
width: max-content;
font-size: clamp(28px, calc(20px + 7vw), 90px);
text-transform: uppercase;
position: absolute;
margin: 0;
transition-property: transform;
transition-duration: 0.1s;
}
.page[data-slide="intro"] h1 {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: clamp(12px, calc(6px + 5vw), 30px);
text-transform: none;
color: #233a43;
}
.page[data-slide="intro"] {
transition-property: opacity, transform;
opacity: 1;
transform: scale(1);
}
.page[data-slide="intro"][data-lisn-page-state="covered"] {
opacity: 0;
transform: scale(0);
}
.page[data-slide="think"] h1 {
top: 3vh;
left: calc(50vw - 3vh);
color: #ffddff;
}
.page[data-slide="outside"] h1 {
transform: rotate(-90deg);
transform-origin: 0% 50%;
bottom: -2vw;
left: 7vw;
color: #4e3e00;
}
.page[data-slide="the"] h1 {
top: 10vh;
left: calc(10vw - 3vh);
color: #233a43;
transform: rotateZ(
calc(
100deg * var(--lisn-js--window-border-height, 1) /
(
var(--lisn-js--window-border-width, 1) +
var(--lisn-js--window-border-height, 1)
)
)
);
}
.page[data-slide="page"] h1 {
bottom: 25vh;
right: 7vw;
color: #ddd;
}
Edit on CodePen
document.addEventListener("DOMContentLoaded", () => {
const pager = document.getElementById("demo");
const pages = pager.querySelectorAll(".page");
new LISN.widgets.Pager(pager, {
pages,
fullscreen: true,
});
// Track the size of the pager (or equivalently we could track the
// window size since the pager is full screen), so that we can
// calculate transforms for several elements.
LISN.watchers.SizeWatcher.reuse().trackSize(null, {
threshold: 0,
target: pager,
});
});
<div id="demo">
<!-- https://www.pexels.com/photo/yellow-black-and-purple-colored-papers-2457284/ -->
<div class="page intro">
<h1>Scroll down (or swipe/drag up)</h1>
</div>
<div class="page w-think">
<img class="background" src="images/pager-think.png" alt="" />
<h1>Think</h1>
</div>
<div class="page w-outside">
<img class="background" src="images/pager-outside.png" alt="" />
<h1>Outside</h1>
</div>
<div class="page w-the">
<img class="background" src="images/pager-the.png" alt="" />
<h1>The</h1>
</div>
<div class="page w-page">
<img class="background" src="images/pager-page.png" alt="" />
<h1>Page.</h1>
</div>
</div>
:root {
--animate-duration: 0.4s;
}
/* Individual pages */
#demo .page {
transition-property: opacity, transform;
box-shadow: none;
opacity: 1;
}
#demo .page[data-lisn-page-state="next"] {
opacity: 0;
}
#demo .page .background {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
#demo .w-think {
z-index: 4;
}
#demo .w-think[data-lisn-page-state="next"] {
transform: translate3d(0px, calc(-100% - 10px), 0px);
}
#demo .w-outside {
z-index: 3;
}
#demo .w-the {
z-index: 2;
}
#demo .w-the[data-lisn-page-state="next"] {
transform: translate3d(calc(-100% - 10px), calc(-100% - 10px), 0px);
}
#demo .w-page {
z-index: 1;
}
#demo .w-page[data-lisn-page-state="next"] {
transform: translate3d(calc(100% + 10px), 0px, 0px);
}
/* Page content */
#demo .page h1 {
width: max-content;
font-size: clamp(28px, calc(20px + 7vw), 90px);
text-transform: uppercase;
position: absolute;
margin: 0;
transition-property: transform;
transition-duration: 0.1s;
}
#demo .intro h1 {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: clamp(12px, calc(6px + 5vw), 30px);
text-transform: none;
color: #233a43;
}
#demo .intro {
transition-property: opacity, transform;
opacity: 1;
transform: scale(1);
}
#demo .intro[data-lisn-page-state="covered"] {
opacity: 0;
transform: scale(0);
}
#demo .w-think h1 {
top: 3vh;
left: calc(50vw - 3vh);
color: #ffddff;
}
#demo .w-outside h1 {
transform: rotate(-90deg);
transform-origin: 0% 50%;
bottom: -2vw;
left: 7vw;
color: #4e3e00;
}
#demo .w-the h1 {
top: 10vh;
left: calc(10vw - 3vh);
color: #233a43;
transform: rotateZ(
calc(
100deg * var(--lisn-js--border-height, 1) /
(
var(--lisn-js--border-width, 1) +
var(--lisn-js--border-height, 1)
)
)
);
}
#demo .w-page h1 {
bottom: 25vh;
right: 7vw;
color: #ddd;
}
Edit on CodePen
<div id="demo" data-lisn-track-size data-lisn-pager="fullscreen">
<!-- https://www.pexels.com/photo/yellow-black-and-purple-colored-papers-2457284/ -->
<div class="page intro">
<h1>Scroll down (or swipe/drag up)</h1>
</div>
<div class="page w-think">
<img class="background" src="images/pager-think.png" alt="" />
<h1>Think</h1>
</div>
<div class="page w-outside">
<img class="background" src="images/pager-outside.png" alt="" />
<h1>Outside</h1>
</div>
<div class="page w-the">
<img class="background" src="images/pager-the.png" alt="" />
<h1>The</h1>
</div>
<div class="page w-page">
<img class="background" src="images/pager-page.png" alt="" />
<h1>Page.</h1>
</div>
</div>
:root {
--animate-duration: 0.4s;
}
/* Individual pages */
#demo .page {
transition-property: opacity, transform;
box-shadow: none;
opacity: 1;
}
#demo .page[data-lisn-page-state="next"] {
opacity: 0;
}
#demo .page .background {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
#demo .w-think {
z-index: 4;
}
#demo .w-think[data-lisn-page-state="next"] {
transform: translate3d(0px, calc(-100% - 10px), 0px);
}
#demo .w-outside {
z-index: 3;
}
#demo .w-the {
z-index: 2;
}
#demo .w-the[data-lisn-page-state="next"] {
transform: translate3d(calc(-100% - 10px), calc(-100% - 10px), 0px);
}
#demo .w-page {
z-index: 1;
}
#demo .w-page[data-lisn-page-state="next"] {
transform: translate3d(calc(100% + 10px), 0px, 0px);
}
/* Page content */
#demo .page h1 {
width: max-content;
font-size: clamp(28px, calc(20px + 7vw), 90px);
text-transform: uppercase;
position: absolute;
margin: 0;
transition-property: transform;
transition-duration: 0.1s;
}
#demo .intro h1 {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: clamp(12px, calc(6px + 5vw), 30px);
text-transform: none;
color: #233a43;
}
#demo .intro {
opacity: 1;
transform: scale(1);
}
#demo .intro[data-lisn-page-state="covered"] {
opacity: 0;
transform: scale(0);
}
#demo .w-think h1 {
top: 3vh;
left: calc(50vw - 3vh);
color: #ffddff;
}
#demo .w-outside h1 {
transform: rotate(-90deg);
transform-origin: 0% 50%;
bottom: -2vw;
left: 7vw;
color: #4e3e00;
}
#demo .w-the h1 {
top: 10vh;
left: calc(10vw - 3vh);
color: #233a43;
transform: rotateZ(
calc(
100deg * var(--lisn-js--border-height, 1) /
(
var(--lisn-js--border-width, 1) +
var(--lisn-js--border-height, 1)
)
)
);
}
#demo .w-page h1 {
bottom: 25vh;
right: 7vw;
color: #ddd;
}