Independence Day Flag Hoist — Free Scroll Animation Snippet

Independence Day Flag Hoist · Scroll · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Entire sequence driven by scroll position — no autoplay, no timeline library, no dependencies
Sticky stage with rAF-throttled, passive scroll listener that reads layout once per frame
phase() helper maps global progress onto per-stage sub-ranges, so re-timing a stage is a two-number change
Unfurl uses animated clip-path rather than scaleX, keeping the Ashoka Chakra perfectly circular throughout
Official flag geometry: 3:2 ratio via CSS calc, equal thirds, chakra at three quarters of the white band
All 24 chakra spokes generated in a loop, pivoting on a shared hub at exact 15-degree intervals
Rolled bundle element rides the pole during the hoist and fades out as the cloth is released
One-shot petal shower with randomised colours and durations that rearms when scrolled back up
prefers-reduced-motion support: petals skipped in JS, wave and sheen keyframes disabled in CSS

About this UI Snippet

Independence Day Flag Hoist — Scroll-Driven Hoisting, Clip-Path Unfurl & a Correct 24-Spoke Ashoka Chakra

Screenshot of the Independence Day Flag Hoist snippet rendered live

Most festive flag animations on the web autoplay on page load, finish before anyone has looked at them, and draw the flag with whatever proportions happened to fit the layout. This snippet takes the opposite approach on both counts. The entire sequence — the bundle climbing the pole, the cloth unfurling, the chakra turning, the petal shower, the greeting — is mapped to scroll position, so the viewer performs the hoisting themselves at their own pace, and every dimension follows the official specification of the Indian national flag.

Scroll progress as the single source of truth

A tall .ind-section holds a position: sticky stage that pins for the duration of the scroll. On every frame the handler reads section.getBoundingClientRect() and computes progress as -rect.top / (section.offsetHeight - window.innerHeight), clamped to 0..1. That one number drives everything else, which means there is no timeline to keep in sync, no autoplay to miss, and scrubbing backwards runs the whole sequence in reverse for free. The scroll listener is registered { passive: true } and throttled through requestAnimationFrame with a ticking flag, so the browser never queues more than one layout read per frame.

Phases that own their own slice of the scroll

A small phase(p, start, end) helper remaps the global 0..1 progress onto a sub-range and clamps outside it, so the hoist runs from 4% to 56% of the scroll, the unfurl from 56% to 78%, and the greeting appears past 85%. Adding or re-timing a stage means changing two numbers rather than restructuring the logic. The hoist itself is passed through an easeOut cubic so the flag decelerates as it reaches the finial, the way a real halyard is eased off at the top.

Unfurling with clip-path instead of a scale transform

The obvious way to open a flag is transform: scaleX() from the pole edge, and it is the wrong one: scaling the container stretches everything inside it, so the Ashoka Chakra becomes an ellipse that only rounds out at the final frame. This snippet animates clip-path: inset(0 N% 0 0) instead, revealing the cloth left to right while every child keeps its true geometry. The chakra is a perfect circle at 1% open and at 100% open. A separate rolled .ind-bundle element rides the pole during the climb and fades out as the unfurl begins, matching the way a flag is actually hoisted furled and then released.

A chakra built to specification

The flag's proportions are 3:2, expressed as --fh: calc(var(--fw) / 1.5) so the ratio holds at every viewport width. Each of the three bands takes an equal third, and the Ashoka Chakra is sized at three quarters of the white band's height — the ratio laid down in the flag code. The 24 spokes are generated in a loop, each one a thin absolutely-positioned bar with transform-origin: 50% 0 pivoting on the hub, rotated by i * 15 degrees. Because the spokes pivot on a shared centre point, the layout is exact rather than eyeballed, and the whole chakra is rotated as a unit by the scroll progress.

Motion that respects the reader

The waving animation is a CSS keyframe on the flag element only, applied via a .waving class once the unfurl completes, so it never fights the inline clip-path the scroll handler is writing. The petal shower is created once in JavaScript with randomised positions, colours and durations, then triggered by a single class toggle — and it rearms if the visitor scrolls back up, so the sequence is repeatable rather than one-shot. A prefers-reduced-motion check skips petal generation entirely and a matching media query disables the wave and sheen keyframes, leaving the scroll-driven hoist itself intact for readers who have asked for less motion.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into an AI assistant like Claude and ask it to add a second scroll stage where the national anthem duration is tracked as a 52-second progress ring beside the flag, which turns the piece into a timed observance rather than a single reveal. Other natural extensions: swap the petal shower for a scroll-driven particle burst that follows the flag's wave phase, add a "half-mast" variant that stops the hoist at 50% for remembrance days, generate the chakra as inline SVG so the spokes can be stroked and animated individually, or drive the same rig from a Web Animations API timeline so the hoist can also be played back on a button press for users who arrive by deep link.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a scroll-triggered Indian Independence Day flag hoisting animation in plain HTML, CSS, and JavaScript — no frameworks, no libraries, no external images.

Requirements:
- A tall section containing a position: sticky stage that pins for the length of the scroll. Compute a single 0..1 progress value from getBoundingClientRect() as -rect.top / (section.offsetHeight - window.innerHeight), clamped.
- Throttle the scroll handler with requestAnimationFrame and a ticking flag, and register the listener as passive. Recompute on resize.
- Map that one progress value onto separate stages with a phase(p, start, end) helper that remaps and clamps to a sub-range: hoist roughly 4%-56%, unfurl 56%-78%, greeting past 85%.
- Stage 1: a rolled flag bundle climbs the pole via translateY, eased with an ease-out cubic so it decelerates at the top.
- Stage 2: the flag unfurls left to right using an animated clip-path: inset(0 N% 0 0) — NOT scaleX, because scaling would distort the chakra. Fade the bundle out as the cloth opens.
- Draw the flag to the official 3:2 ratio using a CSS custom property and calc, with three equal horizontal bands in #FF9933, #FFFFFF and #138808.
- Generate the Ashoka Chakra in JavaScript: exactly 24 navy (#000080) spokes at 15-degree intervals, each absolutely positioned with transform-origin at the hub, inside a circular ring sized to three quarters of the white band height. Rotate the whole chakra with the hoist progress.
- Stage 3: once unfurled, add a class that starts a looping CSS wave animation plus a sheen sweep on the cloth, trigger a one-time shower of falling tricolour petals created in JS with randomised positions and durations, and fade in a "Happy Independence Day / Jai Hind" greeting.
- Make the petal shower rearm if the user scrolls back up, so the sequence is fully reversible.
- Respect prefers-reduced-motion: skip generating petals in JS and disable the wave, sheen and cue keyframes in CSS, while leaving the scroll-driven hoist working.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Scroll into the pinned stageThe intro panel fills the first screen and the stage pins beneath it. From the moment the section enters the viewport, scroll position — not a timer — controls every part of the sequence.
  2. 2
    Watch the bundle climb the poleThrough the first half of the scroll the furled flag rides up the halyard, easing to a stop at the gold finial. The percentage readout at the bottom tracks the hoist so the mechanism stays legible.
  3. 3
    Keep scrolling to unfurl the tricolourPast the top of the pole the cloth opens left to right via an animated clip-path, the rolled bundle fades out, and the warm glow behind the scene lifts as the flag catches the light.
  4. 4
    See the chakra and the petal showerThe 24-spoke Ashoka Chakra turns with the hoist and lands upright, and a shower of tricolour petals falls once the flag is fully open — the way flowers are traditionally tucked into the bundle before it is released.
  5. 5
    Reach the greetingPast 85% of the scroll the "Happy Independence Day / Jai Hind" line fades up beneath the flag, and the flag settles into a slow looping wave with a sheen sweeping across the cloth.
  6. 6
    Scroll back up to replay itEvery stage is derived from scroll position rather than fired once, so scrubbing backwards reverses the whole sequence and the petal shower rearms itself for the next pass.

Real-world uses

Common Use Cases

Independence Day or Republic Day campaign landing page
A scroll-hoisted flag gives an Indian national-day microsite a centrepiece that visitors participate in rather than watch, which holds attention far longer than a looping GIF banner. Pair it with a scroll progress bar so readers can see how much of the story remains.
Festive homepage takeover for an Indian brand or product
Because the whole effect is one section of vanilla HTML and CSS, it can be dropped above an existing homepage for the week around 15 August and removed afterwards without touching the rest of the build or shipping an animation library to every visitor for the rest of the year.
Reference implementation for scroll-linked multi-stage sequences
The phase-mapping pattern here — one clamped progress value fanned out into overlapping sub-ranges — is the correct structure for any scroll-driven story with several beats, whether that is a product exploded view, an onboarding walkthrough, or a data reveal.
Teaching clip-path versus transform for reveal animations
The snippet is a concrete demonstration of why a scale transform is the wrong tool when a revealed element has children with fixed geometry, and it makes the difference visible: the chakra stays round because the reveal clips rather than stretches.
School, college or community event site
Independence Day pages built for institutions usually need to work on old hardware and slow connections. This runs with zero network requests beyond the page itself, no images, and a single rAF-throttled listener, so it stays smooth on low-end Android devices.
CARD
Scroll-triggered hero for any raise, reveal or unveiling metaphor
Swap the tricolour for a product, a banner, or a curtain and the same rig works for any "lift and reveal" hero — the pole, hoist easing, clip-path unfurl and settle-into-motion finish are all independent of the artwork they carry.

Got questions?

Frequently Asked Questions

No. It is plain HTML, CSS, and vanilla JavaScript with zero dependencies and no CDN scripts. The pinning is CSS position: sticky, the progress value comes from getBoundingClientRect(), and the wave and petal motion are CSS keyframes toggled by a class.

Scaling the flag container horizontally stretches every child with it, so the Ashoka Chakra would render as an ellipse until the very last frame. Animating clip-path: inset(0 N% 0 0) reveals the cloth left to right while leaving each child at its true size, so the chakra is a perfect circle at every stage of the reveal.

Yes. The flag is built at the official 3:2 ratio using --fh: calc(var(--fw) / 1.5), the three bands take an equal third each, and the chakra is sized at three quarters of the white band height as specified in the flag code. The chakra is drawn with exactly 24 spokes generated in a loop at 15-degree intervals, each pivoting on the hub.

Adjust min-height on .ind-section — the default 340vh means the stage stays pinned for a little over three screens of scrolling. The stage timings are independent of that: the hoist, unfurl and greeting are expressed as fractions of progress inside the phase() calls, so they stay proportional whatever height you choose.

The JavaScript checks prefers-reduced-motion before generating any petals, and a matching CSS media query disables the wave animation, the sheen sweep, and the scroll cue. The scroll-driven hoist and unfurl still work, since those are direct responses to the user own scrolling rather than autonomous motion.

Yes. Keep refs to the section, flag wrap, flag and chakra, build the chakra spokes and petals in an effect that runs once on mount, and register the scroll and resize listeners in that same effect — returning a cleanup function that removes both. In React use useEffect with an empty dependency array and useRef for the elements; in Vue use onMounted and onUnmounted with template refs; in Angular use ngAfterViewInit and ngOnDestroy with ViewChild.