By
Mark Thurman
May 17, 2025
•
x min read
I had some free time last week. Not uncommon when a project starts; images and copy start slow but become an avalanche later on... So whilst I had some time to fill I took some inspiration from a Webflow legend (Timothy Ricks) and built a small animations library. It took me 4 and a half hours with some Ai help on the tougher bits.
If you're anything like me and enjoy building in Webflow but also crave those slick GSAP animations, you've probably gone down the rabbit hole a few times. It's especially fun now that Webflow and GSAP are now best mates since the acquisition of GSAP by Webflow, and GSAP is now free for everyone. All of which makes adding motion to our Webflow sites so much easier!
Once a site is built I tend to do handle my animations and interactions at the end and I often need to quickly drop in common animation patterns. You know, the sort of thing; classic fade-ins, slide-ups, reveals, staggered lists, and those cool SplitText reveals for headlines ('Tip of the hat' to Timothy Ricks for some inspiration here). These can be a major pain to create in Webflow interactions (at least time consuming) and some of the limitations for loading make them unweildy and not easily portable for other projects.
Setting them up one by one is really repetitive, especially when you're trying to keep things consistent across a site, or even multiple projects. And don't get me started on the very annoying "flash" (FOUC) on hero elements before the animation kicks in!
So, I ended up building a little helper script. It's an attribute-driven system that lets me (and anyone else who wants to try it) add these animations pretty quickly just by tagging elements in Webflow.
What's it do? Basically this:
k-zoom-in
or k-anim="rise-up"
on an element, and it animates on scroll (or on load, more on that later).k-stagger-group
to a parent, and its tagged children animate in sequence. Nice for lists, cards, that sort of thing.SplitText
update. So, things like [words-slide-up]
or [letters-fade-in-random]
on a heading or paragraph will do their magic. I had some help here from Gemini 2.5 to map and merge the required animation trees to ensure we avoid clashes between element animations and text split animations where text is split into lines, words or even characters. . I was stumped on that point - but LLM's are very very good at coding.data-k-loadanim="true"
. This tells the script to fire the animation straight away and it hooks into some CSS to prevent that FOUC. (Flash Of Unstyled Content).k-hideonload
class): This was a bit of a journey, but the system now uses a simple CSS class (.k-hideonload
) that you can add to elements (or stagger group parents/text animation parents) that are above the fold. The CSS hides them initially (but keeps them visible in the Webflow Designer – nifty trick with html.wf-design-mode
!), and the script then smoothly takes over.data-anim-duration
, data-scroll-start
(for scroll-triggered stuff), data-anim-replay
, and data-anim-delay
.
Why Bother if Webflow is Integrating GSAP More Natively?
Yeah, I know, My timing sucks a little as Webflow bought GSAP and are integrating it into the Webflow Interactions interface... I'm sure Webflow's deeper GSAP integration is going to be great and will open up loads of possibilities in the Designer. Time wasted? I dunno, maybe. But one issue with Webflow interactions is that they are often class based, which can mean additional combo classes or wrapper elements, all of which are a management and mental overhead.
I see this little script as a companion to that – a way to have a pre-defined set of my favourite, commonly used animations ready to go with just a few attributes. For me, it's about speed and having a consistent toolkit. If I want a "rise-up" effect, I know exactly what attribute to add.
Quick Look at How to Use It (V2.2):
It boils down to some CSS in your site's <head>
and the main script in your footer.
1. The <head>
CSS (Crucial Bit for FOUC):This hides elements with .k-hideonload
but keeps them visible in the Designer.
<style>
html:not(.gsap-not-found) .k-hideonload { opacity: 0; visibility: hidden; }
html.wf-design-mode .k-hideonload { opacity: 1 !important; visibility: visible !important; }
.k-word, .k-char { display: inline-block; } /* Helps with SplitText transforms */
</style>
<noscript><style>.k-hideonload { opacity: 1 !important; visibility: visible !important; }</style></noscript>
2. Tagging Your Elements:
<div k-zoom-in class="k-hideonload" data-k-loadanim="true">I animate immediately!</div>
<div k-stagger-group class="k-hideonload" data-k-loadanim="true"> <p k-rise-up>Staggered child</p> </div>
<h1 words-slide-up class="k-hideonload" data-k-loadanim="true">Split text on load</h1>
<div k-fade-in data-scroll-start="top 80%">I fade in when I'm 80% from the top.</div>
<p letters-fade-in>These letters fade in on scroll.</p>
(There are more gsap attributes for duration, delay, replay, etc because gsap reallyis a full on animation beast and I'm barely scratching the surface here (but the 80/20 rule is in full effect). – you can see the full setup in the script/guide).
Want to try it or see the code?
I've put the script (it's called V2.2 now) and a more detailed "how-to" guide in my little snippet library. Feel free to grab it, pick it apart, or let me know if you find it useful!
Its only 16kb, and less than 9kb when minified, so its super quick to load with negligable delay.
It's been a fun little project that filled some spare time, and as always with code, probably a perpetual work-in-progress. But for now, it's doing the job for me!
Cheers,
Mark
Book a chat with Mark to see how Koodos can help you