Skip to content
linconkusunokiPublic

About

⚡ Immersive scrollytelling landing page for the Kawasaki Ninja H2R — from black screen to 400 km/h. GSAP + ScrollTrigger, no build step, zero dependencies to install.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kawasaki Ninja H2R — Immersive Scrollytelling Landing Page

A cinematic, single-page scrollytelling experience built around the Kawasaki Ninja H2R. Seven sections take the visitor from a black screen and a cold ignition to 400 km/h, then drop them into silence for a production-allocation request.

No build step. No framework. Plain HTML, CSS and JavaScript with GSAP driving every scroll-linked moment.


Table of contents


Highlights

  • Letter-level text shredding. Every glyph is split into five horizontal strips of irregular height, cut with percentage clip-path. On impact a light bar sweeps the phrase and each strip flies to its own side — the text shreds like paper, it does not simply fade.
  • Cyberpunk camera shake. Randomised, decaying keyframes on a single wrapper element, escalating 26 → 38 → 44 across the three image transitions, plus a continuous 80-frame rumble through the climax.
  • Scroll-driven odometer. A fixed-width digital speedometer climbing 0 → 200 → 300 → 400, locking at 400 with an aggressive red alarm.
  • Blueprint materialisation. A pinned five-stage sketch with leader lines drawn from anchor dot to callout box, accumulating part by part.
  • Hard cut between sections. The rumble's residual transform is explicitly cleared so the conversion section inherits a perfectly still, razor-sharp frame.
  • Zero dependencies to install. GSAP and the fonts load from a CDN.

The seven sections

# Section What happens
1 Hero Headlights blink twice, then burn on. Subtle zoom, scroll hint fades away.
2 Components Bento grid of nine Kawasaki parts (supercharger, motor, painting, chassis, brakes, air, shock, shifter, acceleration). Each card is a full-bleed photo; the description slides up from the bottom on hover or keyboard focus.
3 Sweep Five side-on frames lit laterally, captions stepping in time with the light.
4 Ignition Muted looping video that only decodes while the section is on screen.
5 Sketch Pinned blueprint resolving from wireframe to full motorcycle, four callouts drawing in with measured leader lines.
6 400 km/h Full scrollytelling sequence: text shredding, escalating shake, speed trails intensifying, odometer to 400.
7 Conversion The silence after the storm. Close-up of the front wheel with a faked heat glow on the Brembo disc, glassmorphism panel, neon form.

Tech stack

Layer Choice
Markup Semantic HTML5, lang="en"
Styling Plain CSS — custom properties, Grid, Flexbox, clip-path, backdrop-filter
Animation GSAP 3.12.5 + ScrollTrigger (CDN)
Fonts Syncopate (display), Inter (body), IBM Plex Mono (technical) via Google Fonts
Build tooling None

Project structure

.
├── index.html
├── css/
│   ├── base.css                  reset, base typography, .sr-only utility
│   └── sections/
│       ├── hero.css
│       ├── components.css
│       ├── sweep.css
│       ├── ignition.css
│       ├── sketch.css
│       ├── speed.css
│       └── conversion.css
├── js/
│   ├── main.js                   gsap.registerPlugin — loaded first
│   ├── hero.js
│   ├── components.js
│   ├── sweep.js
│   ├── ignition.js
│   ├── sketch.js
│   ├── speed.js
│   └── conversion.js
└── assets/
    ├── images/
    │   ├── hero/                 h2r-lights-off|on.jpg, logo.png, logo-cutout.png
    │   ├── sweep/                side-0..4.jpg
    │   ├── components/           nine component photographs
    │   ├── speed/                speed-1..3.jpeg
    │   └── sketch/               sketch-1..5.jpeg
    └── video/
        └── turning-on.mp4

CSS and JavaScript are split per section and in page order, so opening css/sections/speed.css next to js/speed.js gives you everything that section needs.

Two naming conventions keep the long single page safe:

  • Sections that were added late are prefixed to avoid colliding with existing rules — .sr-* for the 400 km/h sequence, .cv-* for the conversion section.
  • The JavaScript blocks are wrapped in IIFEs, so section-local constants never leak into the global scope or into each other.

Running it locally

There is nothing to install or build. Because the page loads a video and a handful of JPEGs, open it through a local server rather than file://:

# any static server works
python3 -m http.server 8000
npx serve .

Then visit http://localhost:8000.

If you open index.html directly from the filesystem the layout still renders, but some browsers restrict video playback on the file:// protocol.


How it works

Everything lives in one scrubbed timeline

The speed section is a single gsap.timeline() with scrub: 1, pinned for eight viewport heights. Because scrub maps scroll position onto timeline position, every effect has to be a tween inside that timeline. Firing a shake from a callback with timeline.add(() => gsap.to(...)) creates a real-time tween that desynchronises the moment the user scrolls back up. The helper functions here return vars instead of tweens (shakeVars(), flashVars(), rumbleVars()) and the timeline does the executing.

Timeline positions are data, not magic numbers

const S = { s0: 0.0, s1: 1.2, s2: 3.2, s3: 5.2, end: 8.0 };

The odometer's alarm threshold is derived from these rather than hard-coded, so moving a stage boundary updates everything downstream.

Stagger is included in duration

gsap extends a tween's duration by the whole stagger window. Hiding a line at at + duration — while ignoring the stagger — makes text vanish mid-flight. Both showLine() and tearLine() compute the real duration from the element count and return it, which also keeps the entrance/teardown pair consistent.

The tear

Each character becomes five absolutely positioned strips clipped with percentage clip-path boundaries, jittered per letter so the cuts are never ruler-straight. A hidden sizer span sits in flow to give the letter its box. Words are wrapped in .sr-word (inline-block + nowrap) — without it the browser breaks between adjacent inline-blocks and shreds words down the middle.

Entries animate the ~40 letters; exits animate the ~200 strips. Animating every strip on the way in would be expensive and would not read any differently.


Performance notes

  • Images total ~47 MB at full resolution. Convert to WebP/AVIF and add responsive srcset before shipping this to production.
  • will-change is deliberately not set on the text strips — with ~200 per phrase that would allocate hundreds of GPU layers. GSAP promotes them for the duration of the tween instead.
  • The ignition video is paused whenever its section leaves the viewport, so it stops decoding off-screen.
  • Only one line of text animates at a time.

Accessibility

  • Every animated phrase keeps its full text in an aria-label; the generated letters and strips are aria-hidden. Screen readers never hear a shredded sentence.
  • Interactive cards are tabindex="0" with a :focus-visible ring, so the hover reveal is reachable by keyboard. Without the tabindex, :focus could never fire.
  • The odometer is decorative and marked aria-hidden; its information is in the copy.
  • prefers-reduced-motion: reduce collapses all shakes, strip animations and the odometer alarm to near-zero duration.
  • Form labels are bound to their inputs, and the status line uses role="status" with aria-live="polite".

Browser support

Chrome, Edge, Firefox and Safari (desktop and mobile), current versions. The page relies on CSS clip-path, custom properties, backdrop-filter, Grid and GSAP ScrollTrigger.


Credits and licensing

Product data for the component section is adapted from Kawasaki's official Ninja H2R product page.

⚠️ Image licensing. Every photograph in assets/images/ — the studio shots, the speed frames, the blueprint and the nine component close-ups — is Kawasaki product photography and remains the property of Kawasaki Heavy Industries. They are included here for local development and portfolio demonstration. Obtain the appropriate licence before publishing this project, or swap them for imagery you own.

The conversion form has no backend wired up. Submission is intercepted client-side for validation and a neutral confirmation; nothing is transmitted. Point the <form> at a real endpoint to collect leads.

Trademarks: Kawasaki, Ninja and H2R are trademarks of Kawasaki Heavy Industries, Ltd. This project is not affiliated with or endorsed by Kawasaki.


Built as a front-end portfolio piece.

About

⚡ Immersive scrollytelling landing page for the Kawasaki Ninja H2R — from black screen to 400 km/h. GSAP + ScrollTrigger, no build step, zero dependencies to install.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages