I wished this part to really feel hand-crafted, with a format that has its personal character, although each a part of it’s pushed by Webflow CMS information.
It combines a slot-machine type counter, a manually organized collage of member portraits, and a looping animation that constantly introduces new faces. Each the portraits and the counter are pushed by CMS information, so the part updates mechanically over time.
Getting all of that to work collectively turned out to be the fascinating half. Webflow Assortment Lists are designed to repeat the identical format for each merchandise, whereas this design wants every portrait to have its personal measurement and place.
I wished to unravel that whereas staying contained in the Webflow Designer as a lot as attainable. On this article I’ll stroll via the three methods that made it attainable:
- a configurable slot-machine counter
- a manually organized CMS-powered collage
- a looping GSAP animation in-built Webflow’s visible timeline
Tech stack
- Webflow for the format and construction
- Webflow CMS for the member information and counter worth
- CSS container queries + cqw and em models to scale the collage
- A small JavaScript helper for the counter animation
- GSAP through Webflow’s visible timeline for the looping animation
Half 1: The counter

The counter is the very first thing you see when the part scrolls into view, so it needed to really feel good: a quantity that spins up just like the reels of a slot machine. The quantity comes from a dwell CMS entry that updates each month primarily based on my course gross sales. And since there’s already loads happening within the format, I wished the counter to play first and every part else to comply with, however extra on that animation later.
I can’t write JavaScript myself, so for a bit like this I let AI code it for me, and I’ve actually come to take pleasure in working that approach. A number of years in the past I’d have looked for some snippet on-line and tailored it the place I might. Now it’s fast, and precisely how I would like it. The one half that was difficult was the easing. I wished the final digits to decelerate and settle actually softly on the finish, so it might match the calm really feel of the entire web page, and that precise really feel took a whole lot of backwards and forwards. That’s why I now deal with these items in another way: as an alternative of describing tweaks in phrases, I ask the AI to construct me a small configurator. A number of sliders I can tune myself, till the easing is correct.
These settings have been my suggestions to the AI: they advised it precisely how you can generate the JS. And since I want count-up animations like this in shopper initiatives on a regular basis, I turned it right into a free device you possibly can open and use your self: configure it, export the JS, and set one attribute on a textual content ingredient, the script finds the quantity mechanically. Counter-Up Animation Generator →
How the script works
I can learn the code sufficient to comply with it, however I can’t actually inform whether or not the best way it’s constructed is normal or whether or not there’s one thing intelligent price sharing. So I requested the AI to level out what truly makes this script fascinating, so I might go the important thing concepts on to you. Right here’s the brief model.
The core thought: don’t depend, slide. As a substitute of animating a worth from 0 to its goal, the script builds a vertical strip of digits for every place within the quantity:
- every digit sits in a cell with
overflow: hidden, precisely one line tall - contained in the cell is a strip of stacked numbers (0, 1, 2 … 9, 0, 1 …), as many because the digit must spin, with the goal digit on the very finish
- the strip slides up with
remodel: translateY, and because the cell crops every part however one digit, you see the numbers spin previous till the goal lands
No counting logic, only a cropped, shifting strip:
const e = 1 - Math.pow(1 - p, easePow); // ease-out: the half that took essentially the most tuning
c.strip.type.remodel =
'translateY(' + -(e * c.steps * dh.unit) + dh.css + ')';
Three smaller particulars are what truly made it really feel proper:
Depend the revolutions from the appropriate, not unfold throughout the quantity. I wished the left digit to lock in first and the appropriate one to spin longest. In the event you unfold the spins throughout the entire quantity, the leap from 952 to 1,000 re-sorts each place and the texture shifts. Counted from the appropriate, those place all the time behaves the identical, irrespective of how lengthy the quantity will get:
const proper = chars.slice(idx + 1).filter((c) => /d/.check(c)).size;
const dist = complete - 1 - proper;
const f = dist / maxDist;
const revs = Math.max(1, Math.spherical(revLeft + (revRight - revLeft) * f));
Separate “what number of spins” from “how lengthy it takes.” A pure ease-out begins at full velocity, which feels hectic. Splitting the 2 (revolutions vs. period) is what gave actual management over the texture, and it’s the pair of sliders I spent essentially the most time on:
const steps = revs * 10 + remaining; // how far the digit travels
const myDur = Math.max(0.3, durRight - (maxDist - dist) * stagger); // how lengthy it takes
Learn the actual line-height, don’t hard-code 1em. My heading makes use of a decent line-height: 0.9, so a 1em cell could be too tall and break the spacing under. The script reads the precise line peak with getComputedStyle and strikes the strip in that very same unit:
const cs = getComputedStyle(el);
const lh = cs.lineHeight;
const px = lh === 'regular' ? parseFloat(cs.fontSize) * 1.2 : parseFloat(lh);
And eventually the CMS binding: a tiny second script within the footer reads the actual quantity and exposes it globally. The counter waits for that sign and for an IntersectionObserver to substantiate it’s in view, so it runs precisely as soon as, with the actual quantity, on the proper second, which is what you see within the preview above.
Half 2: A person Webflow CMS collage grid
The goal format

That is the half most individuals assume solely works with customized code or some workaround, and it turned out to be a enjoyable little problem to unravel.
Right here’s the place Webflow will get in the best way. I’ve 4 portraits, at 4 totally different sizes, organized like a collage, however they arrive from a CMS Assortment Checklist. Usually, in order for you a manually-arranged grid, you’ll drop gadgets right into a CSS grid and provides each its personal measurement and place. That works fantastically, however solely exterior of a set checklist. A Webflow CMS Assortment Checklist at the moment doesn’t allow you to set gadgets to particular person positions.
By default, Webflow simply outputs each merchandise the identical approach: identical measurement, identical order, identical repeated textual content beneath. However the design wants every portrait at its personal measurement and place, and that’s the problem.

The important thing realization was that I don’t must reorder the gadgets in any respect, I simply must type every place. In plain CSS you possibly can goal principally any merchandise you need, which is admittedly helpful. Webflow solely offers you 4 of those choices straight within the Designer dropdown:
- first youngster
- final youngster
- odd gadgets
- even gadgets
I wished to see how far I might get with simply these 4, with out writing any customized CSS. It turned out to be sufficient.

So every place will get its personal width, plus a vertical shift on two of them so the tiles don’t sit in a straight row:
/* base width for each merchandise, then override per place, all in em */
.user_grid-item { width: 10em; }
.user_grid-item:first-child { width: 5em; margin-top: 10em; }
.user_grid-item:nth-child(even) { width: 8em; margin-top: 10em; }
.user_grid-item:last-child { width: 6em; }

You might need observed within the default output earlier that Webflow provides the identical title and position label beneath each merchandise, because the CMS repeats the content material for each. The identical youngster selectors deal with this too: with a small CSS embed I disguise all of the labels by default and solely present one per collage, the third merchandise’s label within the prime collage and the second merchandise’s label within the backside one.
.user_grid-item-name { show: none; }
.user_grid-list .w-dyn-item:nth-child(3) .user_grid-item-name { show: block; }
Working with em models to scale the format
Lots of people who comply with my tutorials discover that I work with em right here and there, however haven’t actually introduced it into their very own workflow but. This format is a good instance of why it’s price it.
The precept: in the event you preserve each worth contained in the user_grid-wrapper in em, you possibly can scale the entire format up or down with simply the wrapper’s font-size. Each merchandise resizes with it, no additional work.
Right here’s the way it’s arrange:
- the wrapper will get
container-type: inline-size, which you add as a customized property in Webflow, because it isn’t within the type panel to choose from. That makes the wrapper’s personal width the reference for theemvalues inside it - its
font-sizeis ready to1cqw, one % of that width - as a result of
emis relative to the font-size,1emnow equals one % of the wrapper width, so a 10em merchandise is 10% of it, a 5em merchandise is 5%, and so forth - the
user_grid-wrapperitself sits inside my web page container, which has a max-width
.user_grid-wrapper {
container-type: inline-size;
font-size: 1cqw; /* 1% of the container width */
}
/* gadgets in em then scale with the container mechanically */
.user_grid-item { width: 10em; } /* = 10% of the container width */
All 4 CMS Assortment gadgets scale proportionally with it, along with the gradient form behind them, which is strictly what you need for a graphic like this. Change the bottom font-size and the entire collage grows or shrinks as one piece.
This makes resizing the format, particularly for responsiveness, extremely easy and quick. On cell and pill breakpoint I swap the cqw base for vw, and because the web page container is already full width there, one vw behaves like one cqw. I set the collage to 2vw so it was greater instantly, and the format nonetheless labored out properly.
Half 3: A looping GSAP animation, in-built Webflow’s timeline
For this animation I used Webflow’s new visible timeline. It allows you to construct actual GSAP animations proper within the Designer, with out writing any of the GSAP code your self.
Earlier than animating something, I take into consideration the order issues ought to are available in. It’s a piece in the midst of the web page, so the animation wants an preliminary spark to catch the customer’s consideration, however it additionally shouldn’t occur abruptly, as a result of the format has a whole lot of small particulars and most of them get misplaced if every part strikes on the identical time. So the counter spins up first, and because it slows down the remainder follows. An enormous a part of the work was discovering the candy spot within the timing: how lengthy the counter runs and when the collage gadgets begin swapping, so the gaps don’t really feel too lengthy and the animation retains the viewer’s consideration. All the weather on this part fade in barely staggered.
The masks form gradients additionally scale in a bit of, which supplies them some additional motion.
One factor price doing: I play the timeline on enter, pause on depart, and resume on scroll again, so it isn’t working within the background the entire time and weighing on efficiency.

The 3D member loop impact
The member loop is admittedly the spotlight of the entire animation. Because the part retains filling with actual new members over time, I wished the faces to swap as an alternative of simply exhibiting up as soon as. And since they swap, I wanted an animation each methods, one to convey a set in and one to ship it out, which seems to be particularly good on the textual content because it staggers again out. The setup is easy: every Assortment Checklist sits within the part twice, and the second is positioned place: absolute proper on prime of the primary. It skips forward within the assortment (skip 4, skip eight) so it exhibits totally different faces, after which one checklist animates out whereas the opposite animates in.
The element that makes it look premium is the 3D impact. A plain rotateX by itself seems to be flat: the cardboard simply tilts, however there’s no actual depth to it. The repair is perspective, and the useful half is that you may set perspective and origin straight within the GSAP action-step UI, with out establishing a 3D remodel within the Webflow Designer first.
The settings I used for the incoming photographs:
- Rotate X: -90° to 0°, the precise 3D flip
- Y: 50% to 0%, in order that they transfer up into place
- Scale: 0.7 to 1, rising to full measurement
- Opacity: 0 to 100, fading in
- Perspective: 1000, which is what offers the rotation actual depth
- Stagger: 0.08s offset, ranging from merchandise 4
- Ease: Elastic (Out), for the bounce
The convenience is an enormous a part of the character right here. I wished a bit of bounce-back on the finish, the sort of springy movement you see loads in Apple’s iOS UI. It offers the swap a playful contact, and it really works properly with the calm gradients that simply fade in softly. It’s one thing I plan to reuse throughout the web page, and this part was place to see it work. The good factor about Webflow’s GSAP timeline is that you just choose the curve visually, with a built-in preview, so you possibly can form the elastic precisely the way you need it.

The textual content makes use of its personal impact, cut up line by line so it staggers out and in:
- Transfer Y: 110%, the strains slide up
- Opacity: fading in
- Cut up textual content: by line, with a line masks
- Stagger: 0.035s offset, from the sides
- Ease: Elastic (Out)

Two extra particulars from this stage:
The set motion. Because the two Assortment Lists sit on prime of one another, I preserve the second at opacity: 0 by default within the Webflow Designer, so each aren’t seen without delay whereas I’m working and it stays out of my approach. Within the animation I then use a set motion to change it to full opacity right away, proper in the meanwhile earlier than it animates in, whereas the opposite one is out. It’s not a tween, simply a right away state change on the precise proper time.

Stagger from the skin in. The entire format is constructed across the heart, with the collage unfold out towards the sides, so the swap seems to be finest when it runs from the outer edges inward slightly than left to proper. As a result of every checklist has precisely 4 gadgets, I begin the stagger from merchandise 4, so the pictures swap from the skin towards the counter within the center.

For the loop, my first intuition was to set the entire timeline to repeat infinitely, however that additionally reloops the one-time entrance fade-in, which I positively didn’t need. The clear repair is to separate it into two separate interactions: user-hero-beginning handles the doorway and performs as soon as, and user-hero-collection-loop handles solely the face-swap and repeats infinitely. The timing wants a maintain between swaps, roughly 4 seconds, so the loop is admittedly swap-out, swap-in, pause, repeat.
Accessibility
For diminished movement, the 3D swap loop is an excessive amount of, however the mild fade-in when the part scrolls into view is okay. That is the place splitting the animation into two paid off once more: with the intro fade and the loop as separate interactions, I might preserve the fade for everybody and switch off simply the loop. Webflow’s conditional playback handles it, so guests preferring diminished movement see the part fade in as soon as after which keep nonetheless, with out the faces swapping.

See it dwell
The part is dwell on my FORMBURG course web page.









