
Documentation
Webflow
Code
Setup: External Scripts
External Scripts in Webflow
Make sure to always put the External Scripts before the Javascript step of the resource.
In this video you learn where to put these in your Webflow project? Or how to include a paid GSAP Club plugin in your project?
HTML
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.7/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.7/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.7/dist/Flip.min.js"></script>
Step 1: Copy structure to Webflow
Copy structure to Webflow
In the video below we described how you can copy + paste the structure of this resource to your Webflow project.
Copy to Webflow
Webflow structure is not required for this resource.
Step 1: Add HTML
HTML
<div class="resource-wrapper">
<section class="scaling-element-header"><span class="scaling-element-header__eyebrow">[ Resource ]</span>
<h1 class="scaling-element-header__h1">Scaling element on scroll with Flip</h1>
<div class="scaling-element__small-box">
<div class="scaling-video__before"></div>
<div data-flip-element="wrapper" class="scaling-video__wrapper">
<div data-flip-element="target" class="scaling-video">
<video autoplay="autoplay" muted="" playsinline="" loop="" webkit-playsinline="" class="scaling-video__video"><source src="https://osmo.b-cdn.net/resource-media/scaling-element-resource-185787-876545918_tiny.mp4" type="video/mp4"></video>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 138 138" fill="none" class="scaling-video__svg"><path d="M81.7432 46.534C79.5777 48.6995 75.875 47.1659 75.875 44.1034V0.25H62.125V51.8124C62.125 57.5079 57.5079 62.1249 51.8125 62.1249H0.25V75.8749H44.1034C47.1659 75.8749 48.6996 79.5776 46.5341 81.7431L16.0136 112.263L25.7364 121.986L56.2569 91.466C58.416 89.3069 62.1031 90.825 62.125 93.8693V137.75H75.8751L75.875 86.1874C75.875 80.492 80.4921 75.8749 86.1875 75.8749H137.75V62.1249H93.8692C90.8339 62.1031 89.3157 58.4375 91.4469 56.2759L91.4659 56.2569L121.986 25.7363L112.264 16.0137L81.7432 46.534Z" fill="currentColor"></path></svg>
</div>
</div>
</div>
</section>
<section class="scaling-element-video">
<div class="scaling-element__big-box">
<div class="scaling-video__before"></div>
<div data-flip-element="wrapper" class="scaling-video__wrapper"></div>
</div>
<h1 class="scaling-element-header__h1">And you can have more content here ...</h1>
</section>
</div>
HTML structure is not required for this resource.
Step 2: Add CSS
CSS
.resource-wrapper {
position: relative;
overflow: hidden;
}
.scaling-element-header {
grid-column-gap: 3em;
grid-row-gap: 3em;
flex-flow: column;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 25vh 5vw 20vh;
display: flex;
position: relative;
}
.scaling-element-header__h1 {
text-align: center;
max-width: 9em;
margin-top: 0;
margin-bottom: .25em;
font-size: 7em;
font-weight: 500;
line-height: 1;
}
.scaling-element-header__eyebrow {
color: #9d420a;
text-transform: uppercase;
font-size: 1.25em;
font-weight: 400;
}
.scaling-element-video {
grid-column-gap: 25vh;
grid-row-gap: 25vh;
flex-flow: column;
justify-content: center;
align-items: center;
padding-bottom: 25vh;
padding-left: 5vw;
padding-right: 5vw;
display: flex;
position: relative;
}
.scaling-element__big-box {
border-radius: 1em;
width: 100%;
position: relative;
}
.scaling-element__small-box {
border-radius: 1em;
width: 20em;
position: relative;
}
.scaling-video__wrapper {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.scaling-video {
will-change: transform;
background-color: #d2800f;
border-radius: 1em;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
display: flex;
position: absolute;
top: 0;
left: 0;
overflow: hidden;
isolation: isolate;
transform: translateX(0) rotate(0.001deg);
}
.scaling-video__before {
padding-top: 56.25%;
}
.scaling-video__video {
object-fit: cover;
width: 100%;
height: 100%;
padding-bottom: 0;
padding-right: 0;
position: absolute;
border-radius: inherit;
}
.scaling-video__svg {
color: #fff;
mix-blend-mode: overlay;
width: 6.25em;
position: absolute;
}
@media screen and (max-width: 767px) {
.scaling-element-header__h1 {
font-size: 13.5vw;
}
.scaling-element__small-box {
width: 15em;
}
.scaling-video__svg {
width: 5em;
}
}
Step 2: Add custom Javascript
Custom Javascript in Webflow
In this video, Ilja gives you some guidance about using JavaScript in Webflow:
Step 2: Add Javascript
Step 3: Add Javascript
Javascript
gsap.registerPlugin(ScrollTrigger, Flip);
function initFlipOnScroll() {
let wrapperElements = document.querySelectorAll("[data-flip-element='wrapper']");
let targetEl = document.querySelector("[data-flip-element='target']");
let tl;
function flipTimeline() {
if (tl) {
tl.kill();
gsap.set(targetEl, { clearProps: "all" });
}
// Use the first and last wrapper elements for the scroll trigger.
tl = gsap.timeline({
scrollTrigger: {
trigger: wrapperElements[0],
start: "center center",
endTrigger: wrapperElements[wrapperElements.length - 1],
end: "center center",
scrub: 0.25
}
});
// Loop through each wrapper element.
wrapperElements.forEach(function(element, index) {
let nextIndex = index + 1;
if (nextIndex < wrapperElements.length) {
let nextWrapperEl = wrapperElements[nextIndex];
// Calculate vertical center positions relative to the document.
let nextRect = nextWrapperEl.getBoundingClientRect();
let thisRect = element.getBoundingClientRect();
let nextDistance = nextRect.top + window.pageYOffset + nextWrapperEl.offsetHeight / 2;
let thisDistance = thisRect.top + window.pageYOffset + element.offsetHeight / 2;
let offset = nextDistance - thisDistance;
// Add the Flip.fit tween to the timeline.
tl.add(
Flip.fit(targetEl, nextWrapperEl, {
duration: offset,
ease: "none"
})
);
}
});
}
flipTimeline();
let resizeTimer;
window.addEventListener("resize", function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
flipTimeline();
}, 100);
});
}
// Initialize Scaling Elements on Scroll (GSAP Flip)
document.addEventListener('DOMContentLoaded', function() {
initFlipOnScroll();
});
Step 3: Add custom CSS
Step 2: Add custom CSS
Custom CSS in Webflow
Curious about where to put custom CSS in Webflow? Ilja explains it in the below video:
CSS
Implementation
Wrapper Attribute
We need at least two wrapper elements to define the starting and ending positions for the transition. To do this, add the attribute [data-flip-element="wrapper"]
to each section that should act as a waypoint. The script uses the height, width, and x/y position of each wrapper element to calculate the animation parameters needed to transition to the next wrapper in line. Additionally, you can add more wrappers to create a synchronized animation that transitions smoothly from one section to the next.
Target Attribute
Add the element you want to move and scale as a child of the first wrapper, and assign it the attribute [data-flip-element="target"]
. This element becomes the focal point of the animation, and please note that only one target element is allowed per page.
Extra options
absolute: true;
This solves layout challenges with flexbox, grid, etc.scale: true;
Resize via scaleX/scaleY properties (on default: width/height).ease: "Power1.easeInOut";
Change the ease to animate the ease.scrub: true;
Change this to true to have a more connected scroll feeling.
Learn more about all options in the GSAP Documentation
Resource Details
Last updated
April 17, 2025
Type
The Vault
Category
Scroll Animations
Need help?
Join Slack