Each section occupies the full viewport. Scroll-snap forces the reader into one complete scene at a time, creating a cinematic, story-like rhythm. No partial screens. No fragmented narratives.
A miniature scroll-snap container with 4 sections, distinct gradient backgrounds, breathing radial glows, group-hover parallax layers, and capsule nav dots on the right.
Each section consumes the full viewport.
Scroll-snap locks to section boundaries.
Parallax layers create cinematic depth.
Navigation dots guide the journey.
Scroll inside the demo container. Nav dots update automatically. Hover a section to see group-hover parallax.
Full Page Scroll runs on absolute black (#000000) as the primary canvas, pure white (#ffffff) for content. Four expressive accents — indigo, crimson pink, teal, and amber — each commanding its own full-viewport scene.
Section gradient combinations
The core components that power the full-page-scroll system — nav dots, hero sections, scroll buttons, and content cards.
Capsule nav dots — fixed right side. Active = tall capsule (h-10), hover = medium (h-6), default = circle (h-3)
Click each dot to set active. Hover to see capsule expansion.
Code pattern
<nav className="fixed right-8 top-1/2 -translate-y-1/2 z-50 flex flex-col gap-3">
{/* Active — tall capsule */}
<a className="w-3 h-10 rounded-full bg-indigo-500 transition-all duration-300" />
{/* Inactive — expands to capsule on hover */}
<a className="w-3 h-3 rounded-full bg-white/30
hover:bg-white/80 hover:h-6
transition-all duration-300" />
</nav>Every rule from the aiRules spec is implemented below as an interactive, clickable demo. These are the mandatory patterns any AI generating full-page-scroll code must follow.
Content layers use DIFFERENT transition delays — delay-0 for eyebrow, delay-75 for heading, delay-150 for body. Creates Z-plane depth illusion.
Layer 3 — delay 150ms (slowest)
/* eyebrow */ group-hover:-translate-y-3 delay-0 /* heading */ group-hover:scale-105 -translate-y-2 delay-75 /* body */ group-hover:-translate-y-1 delay-150
An absolute radial-gradient div scales from 1 to 1.1 on group-hover (duration-1000 ease-out). Creates a "room breathing" or "portal opening" sensation without being jarring.
<div className=" absolute inset-0 bg-[radial-gradient(ellipse_60%_50%_at_50%_50%,rgba(99,102,241,0.3),transparent)] group-hover:scale-110 transition-transform duration-1000 ease-out pointer-events-none " />
Side navigation dots morph from circles (h-3) to capsules (h-6) on hover, and tall capsules (h-10) for the active section. Indicates hierarchy without labels.
/* Active */ w-3 h-10 rounded-full bg-accent
/* Hover */ w-3 h-6 rounded-full bg-white/80
/* Default */ w-3 h-3 rounded-full bg-white/30
transition-all duration-300The main heading uses group-hover:scale-105 in addition to translateY. Creates a subtle zoom-in that reinforces the "content approaching" cinematic parallax.
The heading zooms toward the viewer
<h2 className=" group-hover:scale-105 group-hover:-translate-y-2 transition-all duration-700 ease-out delay-75 "> Section Heading </h2>
Full-page scroll is a controlled medium. Each rule protects the cinematic, immersive nature of the experience. Breaking them breaks the spell.
Radical focus
Each section is a complete world. One message, one visual, one call to action. The full viewport is your canvas — waste none of it. Content must never require internal scrolling.
Scroll is the narrative
Scrolling is not navigation — it is page-turning. scroll-snap-type: y mandatory enforces this contract. Every scroll = one complete scene transition. No partial reveals.
Never leave users lost
Side navigation dots, scroll indicators, and section numbers give users the map. Without these, the viewport becomes a trap, not an experience. Always show where you are.
Full-page scroll contact sections use transparent underline-only inputs. They stay visually light against dark backgrounds, letting the gradient breathe. Bold white submit button for maximum contrast.
Input pattern
<input className=" w-full px-0 py-4 bg-transparent border-b border-white/30 text-white text-lg placeholder-white/50 focus:outline-none focus:border-white transition-colors " />
Submit button
<button className=" w-full py-4 mt-8 bg-white text-black font-semibold hover:bg-white/90 transition-colors "> Send Message </button>
Why underline inputs?
Bordered box inputs compete with the dark gradient backgrounds and feel cluttered. Underline-only inputs let the background breathe while keeping the form scannable and purposeful.
<main className={`
h-screen
overflow-y-auto
snap-y snap-mandatory
scroll-smooth
`}>The outermost wrapper. Exactly 100vh, overflow scroll, snap mandatory. Everything happens inside here.
<section className={`
relative min-h-screen
snap-start group
overflow-hidden
flex items-center
justify-center
`}>Every section: full viewport, snap-start, group for parallax, overflow-hidden for breathing glow to stay contained.
<nav className={`
fixed right-8 top-1/2
-translate-y-1/2 z-50
flex flex-col gap-3
`}>
{/* Active: h-10 capsule */}
{/* Hover: h-6 capsule */}
{/* Default: h-3 circle */}
</nav>Fixed to viewport right edge. Morphs between circle and capsule shapes to communicate current position.
Complete container template
<main className="h-screen overflow-y-auto snap-y snap-mandatory scroll-smooth">
{/* Section 1 — Hero */}
<section className="relative min-h-screen snap-start group overflow-hidden
flex items-center justify-center
bg-gradient-to-br from-black via-indigo-950 to-black">
{/* Breathing background (Rule 2) */}
<div className="absolute inset-0
bg-[radial-gradient(ellipse_60%_50%_at_50%_50%,rgba(99,102,241,0.3),transparent)]
group-hover:scale-110 transition-transform duration-1000 ease-out pointer-events-none" />
{/* Staggered content (Rule 1 + 4) */}
<div className="relative z-10 text-center">
{/* delay-0 — fastest */}
<span className="... group-hover:-translate-y-3 transition-transform duration-700 delay-0">01</span>
{/* delay-75 — heading scales */}
<h2 className="... group-hover:scale-105 group-hover:-translate-y-2 transition-all duration-700 delay-75">Title</h2>
{/* delay-150 — slowest */}
<p className="... group-hover:-translate-y-1 transition-transform duration-700 delay-150">Subtitle</p>
</div>
{/* Scroll indicator */}
<button className="absolute bottom-8 left-1/2 -translate-x-1/2 animate-bounce ...">
<ArrowDownIcon className="w-6 h-6" />
</button>
</section>
{/* Repeat sections 2, 3, 4... */}
{/* Fixed capsule nav dots (Rule 3) */}
<nav className="fixed right-8 top-1/2 -translate-y-1/2 z-50 flex flex-col gap-3">
{/* Active */}
<a className="w-3 h-10 rounded-full bg-indigo-500 transition-all duration-300" />
{/* Inactive */}
<a className="w-3 h-3 rounded-full bg-white/30 hover:bg-white/80 hover:h-6 transition-all duration-300" />
</nav>
</main>