How to Master Advanced While-Scrolling Animations in Webflow

This masterclass empowers Webflow designers to recreate sophisticated, award-winning website animations completely code-free by pushing the platform's native features to their absolute limit. The core instruction focuses on a complex scroll interaction where gallery images scale dynamically based on their entry point into the viewport—expanding from the top or bottom depending on scroll direction. By adopting a mindset of "lateral thinking," viewers will learn to bypass standard limitations regarding transform origins and viewport-relative percentages to build professional-grade visual experiences.

A key technical achievement presented is the creation of a robust animation logic that remains accurate across all device aspect ratios. To solve the challenge of varying image heights relative to the viewport, the tutorial demonstrates how to construct invisible "ghost" triggers using calculated CSS heights (calc(100vh - 100%)). This advanced technique ensures that "while scrolling" interactions begin and end precisely when elements enter or leave the screen, providing a level of polish that standard interaction settings often fail to achieve.

Beyond static layouts, the video guides viewers through adapting these complex mechanics for dynamic content using Webflow’s CMS. You will achieve a versatile, responsive gallery system that utilizes custom attributes and embedded CSS calculations to assign specific grid positions and animation classes to dynamic collection items. Ultimately, this resource bridges the gap between design and development, proving that high-end, award-winning motion design is accessible without writing JavaScript.

Key Takeaways

  • Dual-Image Strategy for Transform Origins: To handle scaling animations that must stick to either the top or bottom of the viewport, use two duplicate images per cell—one anchored top-left/right and one bottom-left/right—toggling their visibility based on the scroll direction.
  • Precision Timing with Calculated Triggers: Instead of applying interactions directly to images, use absolutely positioned div blocks (triggers) with a height of calc(100vh - 100%) to perfectly synchronize animation start/end points with the viewport edges.
  • Layering Interaction Types: Combine "While Scrolling in View" for the continuous scaling effect with standard "Scroll Into View" triggers to seamlessly switch visibility between the two duplicate images as the user scrolls up or down.
  • Creative Grid Layouts: For static grids, utilize "empty cell" div blocks to create irregular layouts easily; for CMS layouts, switch to Flexbox and use an Embed element with math-based margins to programmatically position items.
  • Advanced CMS Customization: Overcome CMS limitations by wrapping images in custom elements and using Webflow’s "Attributes" feature to dynamically bind CSS classes (stored in CMS fields) to specific items, enabling unique animations for different collection items.

Timestamps

  • 05:41 – Setting the content wrapper display to Grid with four columns and a 25VW gap.
  • 08:10 – Inserting "empty cell" div blocks into the grid to create spacing for the irregular layout.
  • 10:47 – Wrapping the image element in a div block (gallery section image wrapper) to act as the cell container.
  • 11:12 – Duplicating the image and assigning combo classes (CC1 and cc2) to distinguish the two instances, setting the second to display: none.
  • 12:31 – Configuring the transform origin (e.g., top-left) for the specific combo class (CC top left).
  • 19:42 – Creating the animation trigger div and setting its position to Absolute inside the relative image wrapper.
  • 20:26 – Defining the trigger height using the CSS formula calc(100vh - 100%) to synchronize with viewport height.
  • 21:07 – Positioning the "above" trigger by setting the bottom offset to 100%.
  • 22:17 – Creating the "below" trigger and setting the top offset to 100%.
  • 22:56 – Adding a "While Scrolling in View" interaction set to start when the element is fully visible and end when it scrolls out.
  • 24:23 – Configuring the interaction to target the specific image class rather than the element itself, affecting only siblings.
  • 29:25 – Adding "Scroll Into View" interactions to toggle visibility (display: block vs display: none) between the two duplicate images.
  • 33:33 – Setting pointer-events: none on the trigger elements to prevent them from blocking mouse interactions.
  • 35:54 – Changing the CMS list display to Flexbox (cc-flex) to allow items to spread across rows.
  • 36:33 – Setting the width of CMS items using the calculation calc((100% - 75VW)/4) to account for the three 25VW gaps.
  • 39:03 – Wrapping images in Custom Elements and assigning a class attribute linked to dynamic CMS fields.
  • 41:09 – Adding a Code Embed with CSS to programmatically set margins based on the item's slug.
  • 42:03 – Writing the CSS calculation for margins: calc(margin-right * 25%) to position items based on CMS number fields.
  • 45:14 – Adjusting the item width for mobile responsiveness using calc((100% - 25VW)/2) to allow for two items per row.

Technical Guide: Building Award-Winning Scroll Animations in Webflow

Phase 1: Grid Layout and Static Structure

This phase establishes the irregular grid layout required for the gallery before applying any motion.

1. Configure the Grid Container

  • Timestamp: 04:50 – 05:48
  • How: Create a Section and Container. Inside, add a Div Block (Gallery Section Content Wrapper). Set its Display to Grid, Columns to 4, and Gap to 25vw.
  • Why: This mimics the specific open-space layout of the reference site, ensuring images are spaced widely apart.

2. Implement the "Empty Cell" Strategy

  • Timestamp: 06:39 – 08:59
  • How: Instead of manually positioning images using Grid Child settings, create a Div Block class named Gallery Section Empty Cell. Place these "empty" divs into the grid slots where you don't want images.
  • Why: This "lateral thinking" approach makes populating and rearranging a complex, scattered grid significantly faster than manually defining row/column start-end points for every single image.

Phase 2: The "Dual-Image" Logic

To handle different scaling directions (expanding from top vs. bottom), we must create two versions of every image.

3. Wrap and Duplicate Images

  • Timestamp: 10:19 – 11:46
  • How: Wrap every image element inside a Div Block (Gallery Section Image Wrapper)—this wrapper effectively becomes the grid cell. Inside the wrapper, duplicate the image so there are two instances. Give the first image a combo class CC1 and the second CC2. Set CC2 to Display: None.
  • Why: You cannot dynamically animate a transform-origin property. You need two static images—one anchored to the top and one to the bottom—and toggle between them.

4. Assign Static Transform Origins

  • Timestamp: 11:53 – 14:48
  • How: Apply specific combo classes to your images based on their desired anchor point (e.g., CC Top Left, CC Bottom Right).
    • For the "scaling from bottom" scenario (scrolling down), set the transform origin to the Top corners.
    • For the "scaling from top" scenario (scrolling up), set the transform origin to the Bottom corners.
  • Why: This ensures that when an image scales up, it "sticks" to the correct edge of the viewport.

Phase 3: The "Ghost Trigger" Animation System

This is the core technical achievement of the tutorial. Standard interactions fail here because image aspect ratios vary. We need a trigger that perfectly calculates the scroll distance.

5. Create the Calculated Trigger

  • Timestamp: 19:26 – 20:26
  • How:
  1. Set the Gallery Section Image Wrapper position to Relative.
  2. Add a new Div Block (Gallery Section Animation Trigger) inside it.
  3. Set its position to Absolute.
  4. Critical Step: Set the Height using this CSS calculation: calc(100vh - 100%).
  • Why: This calculation equates to "Viewport Height minus Image Height." It creates a trigger that is exactly the length of the "scroll travel" required for the image to cross the screen, ensuring 100% animation accuracy on any device.

6. Position "Above" and "Below" Triggers

  • Timestamp: 20:53 – 22:32
  • How:
    • Above Trigger: Align its bottom to the top of the image (Bottom: 100%).
    • Below Trigger: Duplicate the trigger, align its top to the bottom of the image (Top: 100%).
  • Why: The "Above" trigger controls the animation when the image enters from the bottom. The "Below" trigger controls the animation when the image enters from the top.

Phase 4: Interaction Setup

Now we connect the motion to the triggers created in Phase 3.

7. Configure "While Scrolling in View"

  • Timestamp: 22:50 – 26:50
  • How:
  1. Select the Above Trigger. Add a While Scrolling in View interaction.
  2. Set boundaries: Start when "Element is fully visible," End when "Element starts scrolling out."
  3. Action: Scale the image siblings from 0 (at 0%) to 1 (at 100%).
  4. Targeting: Target the Class (Gallery Section Image), not the selected element.
  5. Repeat for the Below Trigger, inverting the scale (1 to 0).
  • Why: This creates the smooth expansion/contraction effect. Targeting the class ensures the interaction applies to all images in the grid without making unique interactions for each.

8. Toggle Visibility with "Scroll Into View"

  • Timestamp: 27:04 – 32:00
  • How:
    • Add a standard Scroll Into View interaction to the triggers.
    • Above Trigger: When scrolling in, set Image 1 (CC1) to Block and Image 2 (CC2) to None.
    • Below Trigger: When scrolling in, set Image 1 to None and Image 2 to Block.
  • Why: This swaps the visible image instantly. We show the top-anchored image when scrolling down, and the bottom-anchored image when scrolling up.

9. Cleanup and Polish

  • Timestamp: 32:53 – 33:41
  • How: Remove the helper background colors from the triggers. Set Pointer Events to None on the trigger class.
  • Why: This prevents the invisible triggers from blocking mouse clicks on the actual content.

Phase 5: Adapting for CMS (Advanced)

Standard Grids struggle with irregular layouts in CMS. We switch to Flexbox and math.

10. Switch to Flexbox and Calculated Widths

  • Timestamp: 35:42 – 37:48
  • How: Change the Collection List display to Flex (Wrap). Set the Item width using: calc((100% - 75VW)/4).
  • Why: 75VW accounts for the three gaps of 25VW. This formula dynamically calculates the exact width of a 4-column item regardless of screen size.

11. Custom Attributes and CSS Embeds

  • Timestamp: 38:57 – 42:17
  • How:
  1. Wrap CMS images in a Custom Element.
  2. Add a class attribute linked to a CMS text field (e.g., Image Class).
  3. Add an HTML Embed with CSS that targets items by their slug (using attributes) to set margins via calculation: calc(margin-right * 25%).
  • Why: This allows you to "program" the layout. You can define in the CMS that "Item 5 has a right margin of 3 units," creating the scattered grid effect dynamically.

FAQs

How do I change an element's transform origin based on scroll direction in Webflow?

You cannot dynamically animate the transform-origin property itself. Instead, place two duplicate images within the same container—one anchored top-left and one bottom-left—and use "Scroll Into View" triggers to toggle their visibility (display: block vs. none) as the user scrolls up or down.

How do I fix inaccurate "While Scrolling in View" animation timing across different devices?

Standard percentage offsets often fail due to varying image aspect ratios. Solve this by animating an invisible trigger div positioned absolutely over your element with a height of calc(100vh - 100%), which ensures the interaction duration perfectly matches the viewport travel distance regardless of screen size.

How do I create a scattered or irregular grid layout using Webflow CMS?

Switch your Collection List display to Flexbox and use an HTML Embed containing dynamic CSS. Target items using a custom attribute linked to the item's slug, then apply margins programmatically using a calculation (e.g., calc(margin-right * 25%)) populated by number fields in your CMS.

How can I apply unique classes to specific Webflow CMS items for custom animations?

Wrap your CMS content in a "Custom Element" (instead of a standard Div Block) and add a class attribute to it. Bind this attribute's value to a text field in your CMS collection, allowing you to dynamically assign unique CSS classes and interaction targets to individual list items.

This is some text inside of a div block.