
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.13.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Physics2DPlugin.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/SplitText.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="drop-wrapper">
<div class="drop-section">
<h1 data-drop-text="" class="drop-heading">This is just a<span data-drop-img="" class="drop-heading-img is--first"><img src="https://cdn.prod.website-files.com/681a615bf5a0f1ba3cb1ca38/681a62d0bb34b74d3514ecab_shape-squigle-1.png"></span>random quote<span data-drop-img="" class="drop-heading-img is--second"><img src="https://cdn.prod.website-files.com/681a615bf5a0f1ba3cb1ca38/681a62d0bb34b74d3514ecad_shape-squigle-2.png"></span>we used</h1>
</div>
<div class="drop-section">
<h1 data-drop-text="" class="drop-heading">See how our window acts like<span data-drop-img="" class="drop-heading-img is--third"><img src="https://cdn.prod.website-files.com/681a615bf5a0f1ba3cb1ca38/681a62d0bb34b74d3514ecaf_shape-squigle-3.png"></span> a roof?</h1>
</div>
<div class="drop-section">
<h1 data-drop-text="" class="drop-heading">So much fun!</h1>
</div>
</div>
HTML structure is not required for this resource.
Step 2: Add CSS
CSS
.drop-wrapper {
width: 100%;
min-height: 350vh;
}
.drop-section {
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
display: flex;
position: relative;
}
.drop-heading {
text-align: center;
max-width: 40rem;
margin-top: 0;
margin-bottom: 0;
font-size: 4rem;
font-weight: 500;
line-height: 1;
}
.drop-heading-img {
z-index: 2;
width: 1.2em;
display: inline-block;
position: relative;
}
.drop-heading-img img {
width: 100%;
max-width: 100%;
}
.drop-heading-img.is--first {
transform: rotate(-20deg)translate(.15em, -.2em);
}
.drop-heading-img.is--second {
transform: translate(-.1em, 0.2em)rotate(10deg);
}
.drop-heading-img.is--third {
margin-left: -.1em;
margin-right: -.1em;
margin-top: -.2em;
transform: translate(-.05em, .1em)rotate(50deg);
}
[data-drop-text] .line {
display: block;
}
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, SplitText, Physics2DPlugin);
function initFallingTextGravity() {
new SplitText("[data-drop-text]", {
type: "lines, chars",
autoSplit: true, // resplit split if the element resizes and it's split by lines
linesClass: "line",
onSplit(self) {
// use a context to collect up all the animations
let ctx = gsap.context(() => {
self.lines.forEach((line) => { // loop around the lines
// only one timeline per line rather than one per element
gsap
.timeline({
scrollTrigger: {
once: true, // only fire once
trigger: line, // use the line as a trigger
start: "top top-=10" // adjust offset as you see fit
}
})
.to(line.children, { // target the children
duration: "random(1.5, 3)", // Use GSAP utils for randomized values
physics2D: {
velocity: "random(500, 1000)",
angle: 90,
gravity: 3000
},
rotation: "random(-90, 90)",
ease: "none"
})
.to(line.children,{ // towards the end of the 'fall', fade out the elements
autoAlpha: 0,
duration: 0.2
}, "-=.2");
});
});
return ctx; // return our animations so GSAP can clean them up when onSplit fires
}
});
}
// Initialize Falling Text with Gravity
document.addEventListener("DOMContentLoaded", () => {
initFallingTextGravity();
});
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
[data-drop-text] .line { display: block;}
Implementation
We’re combining the SplitText + Physics2D plugins from GSAP in this one. On scroll your headings shatter into characters and “fall” off the top of the viewport, as if they hit a ‘roof’.
1. Add the target attribute
Add the data-drop-text
attribute to any heading you want to target.
2. Find and split all the targets
In our JS, we create a new SplitText instance for all of our targets. We split the text in lines, and then in separate letters. The lines are used as triggers in our ScrollTrigger (see next step) and the characters of course for our animation. Setting autoSplit
to true
means our SplitText will revert, and then re-init on resize, if our text wraps. That's why we use the onSplit()
callback to create our animation in the next step. A great way to make any SplitText animation responsive easily!
3. ScrollTrigger Setup
In our onSplit
callback, we loop over each line in the heading, inside of a context. This context, which we return at the end, makes sure GSAP can clean up this animation whenever the text re-splits.
In our loop, we create a ScrollTrigger for each line, and we set once: true
, so our animation only fires once. In step 4 we’ll add our animation!
It’s worth playing around with the start
values to really nail the moment where your text visually ‘touches’ the top of the window. For our font, size, and line-height combo, an offset of 10px worked great.
4. Drop the letters with Physics2D
Now, let’s add 2 tweens to our timeline. The first one, using the Physics2D plugin, sends each child element of the line, flying straight down with randomized velocity, angle, and gravity. A second tween makes sure the elements are faded out towards the end.
Definitely have a look around the Physics2D docs to check the values and options you can tweak to really make this exactly like you want it! I'll explain the ones we used:
Velocity
→ The initial velocity of the object measured in pixels per time unit. We used a random value between 500 and 100 to make all letters fall a bit more natural.Angle
→ The initial angle (in degrees) at which the object should travel. This only matters when avelocity
is defined. You could make this a random value between 80 and 100 for example, to make the letters spread out a bit. Just an idea!Gravity
→ The amount of downward acceleration applied to the object, measured in pixels per second. A higher value will mean the letters fall faster.