Webflow scroll animations use two continuous triggers: 'While Scrolling In View' (maps animation to how far an element has scrolled through the viewport) and 'Page Scrolled' (maps to the total page scroll from 0% to 100%). These are distinct from Scroll Into View, which fires once. Use While Scrolling In View for parallax layers and element-specific effects; use Page Scrolled for site-wide progress bars and full-page parallax.
Webflow Scroll Animations: Parallax, Progress Bars, and While-Scrolling Effects
Scroll animations in Webflow are continuous — they map a visual property directly to scroll position rather than playing once. This tutorial covers the three core continuous scroll patterns: a progress bar that fills as the user reads a page, a parallax effect where background elements move at different speeds, and a while-scrolling element animation that transforms as it passes through the viewport. Each uses a different trigger but shares the same principle: keyframes are set at scroll percentages rather than time positions.
Prerequisites
- A Webflow project open in the Designer with a paid site plan
- A long page with multiple sections (scroll animations need vertical scroll distance to work)
- Basic familiarity with the Interactions panel (H)
Step-by-step guide
Enable smooth scrolling for anchor links
Enable smooth scrolling for anchor links
Before adding scroll animations, enable Webflow's built-in smooth scroll for anchor links. Go to Pages panel (P) → select the current page → click the gear icon to open Page Settings → find the 'Smooth Scroll' toggle and enable it. This applies CSS scroll-behavior: smooth to the page, so clicking navigation links that jump to page sections feels fluid. Note: this is separate from scroll animations — it only affects anchor link navigation, not the animations you'll add next.
Expected result: Clicking anchor navigation links now scrolls smoothly to target sections instead of jumping instantly.
Build a scroll progress bar using Page Scrolled trigger
Build a scroll progress bar using Page Scrolled trigger
Add a Div Block to the canvas. Give it class 'progress-wrap'. In Style Panel (S): Position → Fixed, Top → 0px, Left → 0px, Width → 100%, Height → 4px, Z-index → 9999 (Position must be set to Fixed or Sticky for Z-index to appear), Background Color → transparent. Inside 'progress-wrap', add another Div Block with class 'progress-bar'. Style 'progress-bar': Width → 0%, Height → 100%, Background Color → your brand accent color. Now go to Interactions panel (H) → Page triggers → '+' → 'Page Scrolled'. In the animation timeline, add two keyframes: at 0% scroll — set Width of 'progress-bar' to 0%; at 100% scroll — set Width to 100%. The bar now fills proportionally as the user scrolls the entire page.
Expected result: A thin horizontal bar at the very top of the viewport fills from left to right as the user scrolls, reaching 100% width at the bottom of the page.
Create a parallax background layer
Create a parallax background layer
Select a section that has a background image or contains decorative elements. Inside the section, add a Div Block class 'parallax-layer' with a background image. Set it Position Absolute, Top -20%, Left 0, Width 100%, Height 140% (larger than the section so it doesn't clip during movement). Select 'parallax-layer'. Go to Interactions panel (H) → Element triggers → '+ Add trigger' → 'While Scrolling In View'. In the animation timeline, set two keyframes: at 0% (element enters viewport from bottom) — Move Y: 0px; at 100% (element exits viewport at top) — Move Y: -80px. The layer moves upward more slowly than the viewport scroll speed, creating the parallax depth illusion.
Expected result: As the section scrolls through the viewport, the background layer moves at a different speed, creating a layered 3D depth effect.
Animate element content while scrolling through viewport
Animate element content while scrolling through viewport
Select a text block or card inside a section. Give it class 'scroll-animate'. Go to Interactions panel (H) → Element triggers → '+ Add trigger' → 'While Scrolling In View'. Set keyframes: at 0% — Opacity 0.5, Move X -40px; at 50% — Opacity 1, Move X 0px; at 100% — Opacity 0.5, Move X 40px. This creates a continuous animation where the element slides in from the left as it enters the viewport, centres at full opacity in the middle of its scroll journey, then slides out to the right as it leaves. The animation reverses as the user scrolls back up.
Expected result: The element slides and fades as it travels through the viewport — fully visible in the centre, partially transparent and offset at the edges.
Set scroll animation offset and smoothing
Set scroll animation offset and smoothing
In the Interactions panel with the 'While Scrolling In View' trigger selected, look for the Offset sliders. The top offset (Start %) defines how far into the viewport the element needs to be before the animation begins. The bottom offset (End %) defines when to stop. Set Start to 15% and End to 15% to create a buffer — the animation won't start until the element is 15% into the viewport. Find the Smoothing slider and set it to 30–40%. Smoothing adds a lag between the actual scroll position and where the animation is — this makes scroll-driven motion feel organic rather than mechanically locked to the scroll speed.
Expected result: Animations no longer snap to exact scroll position — they have a slight follow-through that makes the motion feel physical.
Build a sticky header that shrinks on scroll
Build a sticky header that shrinks on scroll
Select your navbar element. Ensure it has Position Fixed (Style Panel → Position → Fixed, Top 0, Z-index 1000). Give it class 'nav-bar' with Height 80px. Go to Interactions panel (H) → Page triggers → '+' → 'Page Scrolled'. In the timeline, add keyframes: at 0% — Height 80px on 'nav-bar'; at 10% — Height 50px. This causes the navbar to shrink once the user scrolls 10% down the page. Add a Transition on the 'nav-bar' element: Style Panel → Effects → Transitions → '+' → Property: Height, Duration 300ms, Ease — this smooths the height change so it doesn't snap.
Expected result: The navbar smoothly shrinks in height and changes background as the user scrolls past the hero section.
Use While Scrolling In View on a section's children for staggered scroll reveals
Use While Scrolling In View on a section's children for staggered scroll reveals
Select the parent section wrapper. Go to Interactions panel (H) → Element triggers → '+ Add trigger' → 'While Scrolling In View'. Set keyframes: at 0% — Move Y 60px, Opacity 0 on 'Affect class: scroll-child' with 'Limit to nested elements'; at 30% — Move Y 0, Opacity 1. This is a hybrid approach: the reveal completes early in the scroll journey (at 30%) so the element is fully visible by the time it reaches the viewport centre. Toggle the 'Play once' equivalent by setting the 100% keyframe to keep Move Y 0, Opacity 1 — maintaining the final visible state.
Expected result: Child elements inside the section animate in as the section scrolls through the viewport, and stay visible once the entrance portion of the scroll journey is complete.
Complete working example
1// Add to Page Settings > Before </body> Code if you need smooth scroll2// for ALL scrolling (not just anchor links) on older browsers.3// Webflow's native Smooth Scroll toggle handles anchor links automatically.45// For programmatic smooth scrolling to a specific element:6document.querySelectorAll('a[href^="#"]').forEach(anchor => {7 anchor.addEventListener('click', function(e) {8 e.preventDefault();9 const target = document.querySelector(this.getAttribute('href'));10 if (target) {11 target.scrollIntoView({12 behavior: 'smooth',13 block: 'start'14 });15 }16 });17});1819// Note: Webflow's built-in smooth scroll (Page Settings > Smooth Scroll)20// handles this automatically for most use cases. Only use this script21// if the built-in toggle is not sufficient for your implementation.Common mistakes
Why it's a problem: Progress bar is visible but stays at 0% width and never fills
How to avoid: The Page Scrolled trigger animation is animating the wrong element, or the keyframes are set to a fixed pixel value instead of percentage width. Check the animation target — it should be targeting the inner 'progress-bar' div, not the outer 'progress-wrap'. Also confirm you are setting Width as a percentage (0% → 100%), not pixels — pixel widths do not scale with the viewport.
Why it's a problem: Parallax layers clip and show white gaps below the section on scroll
How to avoid: The parallax layer is not tall enough to cover the section during movement. Set the parallax layer Height to 120–140% of the section height and keep its Position Absolute with a negative top offset to cover the section top during upward movement. The outer section must have Overflow Hidden (Style Panel → Size → Overflow → Hidden) to clip the oversized layer.
Why it's a problem: While Scrolling In View animation plays backwards when the user scrolls back up
How to avoid: This is expected behaviour — While Scrolling In View is bidirectional by design. If you want a one-time entrance that doesn't reverse on scroll-up, use Scroll Into View with 'Play once' enabled instead. If you need While Scrolling In View but want to lock the final state, set your 100% keyframe to the fully-visible state so the element appears complete after the animation finishes in either scroll direction.
Why it's a problem: Scroll animations cause janky performance on the live site even though they look smooth in Preview
How to avoid: You are likely animating layout-triggering properties (Width, Height, Margin, Padding, Top, Left). Replace these with Transform equivalents: use Move X/Y instead of Left/Top, use Scale instead of Width/Height changes. Also reduce the number of simultaneous while-scrolling animations — each one recalculates on every scroll frame. Limit to 3–5 maximum per page.
Best practices
- Use Page Scrolled for site-wide effects (progress bars, navbar shrink) and While Scrolling In View for element-specific parallax
- Keep parallax Move Y ranges small (40–100px) — large values create jarring motion and break the visual relationship between layers
- Set Smoothing between 20–50% for natural-feeling scroll animations — 0% feels mechanical, >70% causes confusing post-scroll continuation
- Animate only Transform (Move, Scale, Rotate) and Opacity in scroll animations — avoid Width, Height, and Margin which cause layout reflow on every scroll frame
- Test scroll animations with keyboard-only navigation — users who navigate with Page Down/Up keys should not miss content hidden by scroll-triggered states
- Use scroll offset (15% buffer) so animations don't fire the instant 1px of an element enters the viewport
- Disable while-scrolling animations on mobile via Interactions panel breakpoint checkboxes — they require constant recalculation and drain battery
- Clean unused scroll interactions with the Interactions panel broom icon — orphaned Page Scrolled triggers run on every scroll event even if their targets don't exist
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building a Webflow landing page and want three scroll animation effects: 1) a thin progress bar at the top of the page that fills as the user scrolls, 2) a parallax background image that moves slower than the page scroll speed, 3) a navbar that starts transparent and gains a white background with a slight height reduction once the user scrolls 10% down. Explain which Webflow Interactions triggers to use for each (Page Scrolled vs While Scrolling In View) and give me the exact keyframe values to set.
Build a scroll progress bar: add a fixed-position div 'progress-wrap' at top 0, full width, 4px height, z-index 9999. Inside add 'progress-bar' starting at 0% width. Add Page Scrolled interaction: at 0% scroll set progress-bar width to 0%, at 100% scroll set width to 100%. Also set up a While Scrolling In View parallax on 'parallax-layer' inside the hero section: at 0% move Y 0px, at 100% move Y -80px.
Frequently asked questions
What is the difference between Scroll Into View and While Scrolling In View?
Scroll Into View fires once — when the element enters the viewport it plays an animation (like a fade-in), and you can set it to play only once. While Scrolling In View is continuous — the animation progress is mapped directly to how far the element has traveled through the viewport, so it plays forward as the user scrolls down and in reverse as they scroll back up. Use Scroll Into View for entry reveals; use While Scrolling In View for parallax and continuous transform effects.
Can I make a scroll animation play only in one direction (not reverse on scroll-up)?
While Scrolling In View is inherently bidirectional and cannot be set to play only on scroll-down. For a one-directional reveal, use the Scroll Into View trigger with 'Play once' enabled instead. The trade-off is that Scroll Into View plays a timed animation in one burst, while While Scrolling In View gives you scrubbing control tied to exact scroll position.
How do I make the scroll progress bar work on CMS collection pages?
The Page Scrolled interaction is added per-page or per-template in Webflow. To add it to CMS template pages (blog posts, case studies, etc.), open the CMS Collection Page template in Pages panel (P) → CMS Collection Pages → your template. Add the progress-wrap and progress-bar elements there, then create the Page Scrolled interaction on that template. Every item in that collection will automatically inherit the progress bar.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation