🚨 UPDATE: The Scroll-Linked Animations Specification and its proposed syntax have undergone a major rewrite. This post details an older version of the syntax and has not been updated to reflect these changes.
Do note that the concept of a Scroll-Linked Animation still stands, it’s only the syntax that has changed since writing this. Please refer to https://developer.chrome.com/articles/scroll-driven-animations/ for an article with examples that use the updated syntax.
Example Scroll-Linked Animation with Element-Based Offsets, CSS FTW! 🤩
The Scroll-linked Animations Specification is an upcoming addition to CSS that defines a way for creating animations that are linked to a scroll offset of a scroll container. Even though the specification is still in draft, and in no way finalized nor official, it already has experimental support in Chromium.
In the first part of this series we covered how to create Scroll-Linked Animations between two absolute scroll-offsets using the @scroll-timeline
at-rule and animation-timeline
CSS property.
In this second part we dial it up a notch and dig into creating Scroll-Linked Animations based on the location of an element within its scroller.
~
👨🔬 The CSS features described in this post are still experimental and not finalized at all! If you’re feeling adventurous you can play with these new features today, but you’ll need at least Chromium 89 with the #experimental-web-platform-features
flag enabled through chrome://flags
.
💥 To keep your primary Chrome install clean, I recommend you do not set this in Chrome Stable, but resort to Beta / Canary builds.
👀 If you don’t understand how to do this, or don’t feel safe doing this, fear not: This post also includes recordings and/or fallback versions using JavaScript for most of the demos.
💄 While the Scroll-Linked Animations Specification also describes a JavaScript interface, the main focus of this post will be its CSS counterpart. The JS alternatives won’t be covered in detail.
~
Table of Contents
~
# Scroll-Linked Animations (Part 1), a Recap
In the first part of this series we took a look at @scroll-timeline
and its descriptors. If I explained it all properly, the code snippet below should make sense:
@keyframes resize-progressbar {
to {
transform: scaleX(1);
}
}
@scroll-timeline scroll-in-gallery {
source: selector(#gallery__scrollcontainer);
scroll-offsets: 0%, 100%;
orientation: horizontal;
time-range: 1s;
}
#gallery__progressbar {
transform: scaleX(0.5);
animation: 1s linear forwards resize-progressbar;
animation-timeline: scroll-in-gallery;
}
🚨 It’s very important to understand the contents of the first part of this series as this post builds further upon that knowledge. If you haven’t read it, you most likely won’t understand all that much of this second part. You can read the first part here.
~
# Element-based Offsets?
Besides setting absolute values as scroll-offsets
, the Scroll-Linked Animations Specification also allows you to set Element-based Scroll Offsets. With this type of Scroll Offsets the animation is based on the location of an element within the scroll-container.
Typically this is used to animate an element as it comes into the scrollport until it has left the scrollport; e.g. while it is intersecting:
See the Pen Scroll-Linked Animations Visualization: Element-Based Offsets by Bramus (@bramus) on CodePen.
When scrolling down in the visualization (using the ⏭ button) you’ll see the box switch colors:
- as it slides into the scrollport from the bottom
- after it has just left the scrollport at the top
🔄 When scrolling back up again you’ll see the same happening in reverse.
Both these turning points can be used as offsets for a Scroll-Linked Animations. Because they are described from the perspective of the box itself (which is an HTML Element), we call these “Element-based Offsets”.
In pseudo-code, our @scroll-timeline
would look like this:
@scroll-timeline element-enters-and-leaves-the-scrollport {
scroll-offsets:
“the box is positioned underneath the bottom edge of the scrollport”,
“the box is positioned above the top edge of the scrollport”
;
time-range: 1s;
}
As with “regular” Scroll-Linked Animations we can drive an animation while scrolling between these two Element-based Offsets.
☝️ In an earlier version of the spec one had to define the Scroll Offsets using start
and end
descriptors.
@scroll-timeline element-enters-and-leaves-the-scrollport {
start: “the box is positioned underneath the bottom edge of the scrollport”;
end: “the box is positioned above the top edge of the scrollport”;
time-range: 1s;
}
This is no longer the case, and one should now use the scroll-offsets
descriptor instead.
However, you might still see this older syntax in the demos as Chromium has this older version implemented and is in the process of migrating to the new scroll-offsets
syntax — Relevant Chromium Bug: 1094014
~
# Element-based Offsets in CSS
To create a Scroll-Linked Animation that uses Element-based Offsets, we first need two Element-based Offsets:
- A from offset which defines when the animation will begin.
- A to offset which defines by when the animation will be done.
In CSS, these Element-based Offsets are represented by the <element-offset>
Data Type.
~
# The <element-offset>
Data Type
Let’s take the example below and dissect it:
selector(#element) end 0
selector(#element)
defines the DOM Element we want keep an eye on. We call this the target.-
end
indicates at which edge of thesource
‘s scrollport the algorithm should look for thetarget
intersecting.- Allowed values are
start
/end
. - Depending on the timeline’s
orientation
this translates to the top/bottom or left/right edge.
- Allowed values are
-
The threshold is a number — ranging from
0.0
to1.0
— that indicates how much of the target is visible in the scrollport at the given edge.0
= not in the scrollport1
= entirely in the scrollport
You might already know this value from creating an
IntersectionObserver
.
Looking back at our example of selector(#element) end 0
, it basically translates to:
- Keep an eye on
#element
… - … and track if it intersects at the
end
edge ofsource
. - If the element’s intersecting threshold is
0
then activate.
E.g. the #element
is touching the scrollport at its bottom edge; which happens to be the starting point from the visualization before!
~
# Making it visual
If you cannot follow with that threshold there, don’t worry: it’s easier to understand if you make it visual.
See the Pen Scroll-Linked Animations Visualization: Element-Based Offsets Visualizer by Bramus (@bramus) on CodePen.
In the visualization above try changing the values, keeping in mind that the threshold is a number that indicates how much of the target is intersecting with the scrollport at the given edge.
If, after playing with it, you understand that a edge+threshold combo of start 0.5
means that the target is halfway across the top edge of a vertical scrollport, you get it 😎
🐛 I’ve noticed that it’s also possible to — for example — define end 1.2
, which translates to “the target is 1/5th over the bottom edge”. This is not allowed per spec, as the threshold should be in the range of 0.0
and 1.0
.
However, as the algorithm never checks whether this value is inside its assigned range, it passes through and will work. I kinda like this quirk, as it allows you to add some breathing room to all of your animations.
Could be in the future that this will no longer be allowed — Relevant CSS WG Issue: 5203
~
# Element-based Offsets and @scroll-timeline
(Revealing Image Demo)
To create a Scroll-Linked Animation that uses Element-based Offsets, you need to pass a pair of <element-offset>
Data Types into the @scroll-timeline
‘s scroll-offsets
descriptor.
@scroll-timeline element-enters-and-leaves-the-scrollport {
scroll-offsets:
selector(#element) end 0,
selector(#element) start 0
;
time-range: 1s;
}
selector(#element) end 0
here is our from offset, and defines when the animation will begin.selector(#element) start 0
here is our to offset, and defines by when the animation will be done.
Here the offsets for our @scroll-timeline
are set so that the animation will begin when #element
is about to enter the scrollport from the bottom (= end
edge, 0
% in view), and will be done animating after the #element
has entirely left the scrollport at the top (= start
edge, 0
% in view).
See the Pen Scroll-Linked Animation with Element-Based Offset (@scroll-timeline version) by Bramus (@bramus) on CodePen.
See the Pen Scroll-Linked Animation with Element-Based Offset (JS WAAPI Version) by Bramus (@bramus) on CodePen.
In this demo you’ll see an image be revealed as it intersects with the scrollport. The reveal itself is done using a clip-path
that animates from inset(0% 50% 0% 50%);
to no clipping at all, which looks like a curtain opening.
@keyframes reveal {
to {
clip-path: inset(0% 0% 0% 0%);
}
}
.revealing-image {
clip-path: inset(0% 50% 0% 50%);
animation: reveal 2s linear;
animation-fill-mode: forwards;
}
@scroll-timeline revealing-image-timeline {
source: selector(body);
scroll-offsets:
selector(#revealing-image) end 0,
selector(#revealing-image) start 0
;
time-range: 2s;
}
#revealing-image {
animation-timeline: revealing-image-timeline;
}
🤕 In this demo we have a loss of (visual) data though. As our animation reaches 100% only when the image has already slid out of scrollport (at the top), we can never see the image as a whole — it’s always clipped while inside the scrollport. Thankfully we can tweak the used <element-offset>
s to prevent this loss of visual data.
~
# Typical from/to <element-offset>
Combinations
There are 4 typical edge
+ threshold
combinations to use with Scroll-Linked Animations:
start 0
start 1
end 1
end 0
☝️ As a reminder, here’s what they look like, individually:
See the Pen Scroll-Linked Animations Visualization: Element-Based Offsets Visualizer by Bramus (@bramus) on CodePen.
Other values for threshold of course still possible; I’m only taking a look at these extremes here.
Depending on how you combine these as to/from offsets, we can control when exactly the animation will run:
#element
is intersecting scrollport, even for the tiniest bit#element
is in between scrollport edges#element
is entering from bottom into scrollport#element
is exiting at top from scrollport
In the demo below I’ve created several boxes that each have a different pair of <element-offset>
s applied. Scroll down to see the elements appear in the viewport and take a good look at each box separately, specifically when one of its edges enters or leaves the viewport.
Color codes are applied to indicate when the element is being animated:
- Red = the Scroll Timeline is not animating the element
- Green = the Scroll Timeline is animating the element
See the Pen Scroll-Linked Animations: Element-Based Offsets Comparison (@scroll-timeline version) by Bramus (@bramus) on CodePen.
Unfortunately there’s an issue with the used ScrollTimeline polyfill used, and the timelines are calculated wrongly. Showing this (broken) demo would only confuse you more, so it’s not included. Please to see how it behaves.
Did you see? Hit the checkbox at the top to have the demo show the findings. Perhaps you’ll see it now 😉
Interpreting the results from the demo, I’ve forged this small list of typical from-to offset combinations and what they look like:
end 0
→start 0
= intersecting scrollport, even for the tiniest bitend 1
→start 1
= in between scrollport edgesend 0
→end 1
= enter from bottom into scrollportstart 1
→start 0
= exit at top from scrollport
In this extra visualization below you can see how these different combinations affect the timeline (drawn in the center). The same colors as in the demo are used.
See the Pen Scroll-Linked Animations Visualization: Element-Based Offsets Timeline Visualizer by Bramus (@bramus) on CodePen.
🥵 Don’t sweat it if you don’t understand this all immediately; it also took me quite some time before I did. And perhaps there’s no need to, as you can go a long way with this little cheat sheet:
end 0
→start 0
= intersecting scrollport, even for the tiniest bitend 1
→start 1
= in between scrollport edgesend 0
→end 1
= enter from bottom into scrollportstart 1
→start 0
= exit at top from scrollport
~
💁♂️ Like what you see so far? Happen to be conference or meetup organiser? Feel free to contact me to come speak at your event, with a talk covering the contents of this post.
~
# Demos
As I have been playing with CSS @scroll-timeline
for nearly a month by now, I’ve whipped up quite a lot of extra demos. Ready to have your socks blown off? Here goes:
- Revealing Images Demo, Revisited
- Contact List Demo
- Contact List Demo, Revisited
- Horizontal Scroll Section Demo
- CoverFlow Demo
- Stacking Cards Demo
☝️ Know that all these demos here are technical demos. On a real website you might want to go easy with these types of animations in case visitors request so, by respecting their prefers-reduced-motion
setting.
~
# Revealing Images Demo, Revisited
This demo is similar to the first Revealing Image one, yet the offsets were tweaked in such a way that the revealing animation should only start when the image is already halfway in view (read: threshold of 0.5
) and be finished by the time the image has entered the scrollport completely.
See the Pen Scroll-Linked Animation: Image Reveal as it scrolls into view (@scroll-timeline version) by Bramus (@bramus) on CodePen.
See the Pen Scroll-Linked Animation: Image Reveal as it scrolls into view (JS WAAPI + ScrollTimeline Version) by Bramus (@bramus) on CodePen.
In @scroll-timeline
speak that becomes:
@scroll-timeline revealing-image-timeline-1 {
source: selector(body);
scroll-offsets:
selector(#revealing-image-1) end 0.5,
selector(#revealing-image-1) end 1
;
time-range: 2s;
}
Above that the start clip-path
was set to inset(45% 20% 45% 20%);
— making it look like a revealing box — and the opacity
is also animated.
.revealing-image {
opacity: 0;
clip-path: inset(45% 20% 45% 20%);
…
}
~
# Contact List Demo
In this demo I’ve created a contact list where new items slide in when they enter the scrollport. I think it makes a neat effect 🙂
See the Pen Fly-in Contact List (CSS @scroll-timeline version) by Bramus (@bramus) on CodePen.
See the Pen Fly-in Contact List (JS WAAPI + JS ScrollTimeline version) by Bramus (@bramus) on CodePen.
The list itself is a regular <ul>
which acts as the @scroll-timeline
‘s source. Each <li>
has it’s own scroll-offset
set to go from end 0
(= bottom edge, out of view) to end 1
(= bottom edge, in view).
@keyframes slide-in {
to {
opacity: 1;
transform: translateX(0);
}
}
li {
opacity: 0;
transform: translateX(-100%);
animation: 1s slide-in ease-in forwards;
}
@scroll-timeline list-item-15 {
source: selector(#list-view);
scroll-offsets:
selector(#list-item-15) end 0,
selector(#list-item-15) end 1
;
time-range: 1s;
}
#list-item-15 {
animation-timeline: list-item-15;
}
😳 ICYWW: No, I didn’t manually type out all those scroll-timeline
s
As also mentioned in the first part of this series it’s pretty annoying when it comes to creating scroll-timeline
s for many individual items as the selector()
function requires you to pass an id
into it. This is a shortcoming of the spec, and is something what will be tackled. Relevant CSS WG Issue: 5884
Until this issue is resolved — and to save myself from typing all those scroll-timeline
s out manually — I use a little piece of JavaScript to generate the timelines. These generated timelines can then be either copy-pasted into the CSS, or dynamically injected from the script.
const generateCSS = () => {
const css = [];
document.querySelectorAll('li').forEach((li, i) => {
const id = li.getAttribute('id');
css.push(`
@scroll-timeline list-item-${id} {
source: selector(#list-view);
scroll-offsets:
selector(#${id}) end 0,
selector(#${id}) end 1
;
time-range: 1s;
}
#${id} {
animation-timeline: list-item-${id};
}
`);
});
return css.join("\n");
}
const injectCSS = (css) => {
const style = document.createElement('style');
style.innerHTML = css;
document.head.appendChild(style);
}
injectCSS(generateCSS());
In some demos you might notice that the generateCSS()
code is still present, but not called. And even if it were: those demos still are pure CSS 😉
The animation on the <li>
s in this demo was carefully chosen to be a horizontal one, so that the dimensions of the of the wrapping <ul>
‘s scrollport don’t change. If the <li>
elements would be translated in a vertical direction, that would also adjust the scrollport. You can work around this by animating not the <li>
itself, but by animating its contents.
🔥 TIP: Beware with animations that alter the dimensions of the source
‘s scrollbox. Work around it by not animating the target, but by animating the target’s contents.
💡 By flipping the animation and adjusting the scroll-offsets
so that they are triggered at the start
edge, you can easily create a version where items slide-out as they scroll out of the scrollport.
@keyframes slide-out {
to {
opacity: 0;
transform: translateX(100%);
}
}
li {
opacity: 1;
transform: translateX(0);
animation: 1s slide-out ease-in forwards;
}
@scroll-timeline list-item-1 {
source: selector(#list-view);
scroll-offsets:
selector(#list-item-1) start 1,
selector(#list-item-1) start 0
;
time-range: 1s;
}
#list-item-1 {
animation-timeline: list-item-1;
}
~
# Contact List Demo, Revisited
Combining both the fly-in and fly-out effect is possible by creating 2 animations, each with their own individual (non-overlapping) @scroll-timeline
/* Element scrolls into the scroll-container (from the bottom) */
@scroll-timeline tl-list-item-12-appear {
source: selector(#list-view);
scroll-offsets:
selector(#list-item-12) end 0,
selector(#list-item-12) end 1
;
time-range: 1s;
}
/* Element scrolls out of the scroll-container (at the top) */
@scroll-timeline tl-list-item-12-disappear {
source: selector(#list-view);
scroll-offsets:
selector(#list-item-12) start 1,
selector(#list-item-12) start 0
;
time-range: 1s;
}
#list-item-12 > * {
animation:
1s li-appear linear tl-list-item-12-appear,
1s li-disappear linear tl-list-item-12-disappear
;
}
See the Pen Scroll-Linked Animations: Fly-In Contact List (Fly-In + Fly-Out) by Bramus (@bramus) on CodePen.
🥳 Got it working, after kevers@ pointed out that the `animation-fill-mode: both;` was the culprit messing things up.
— Bramus! (@bramus) February 25, 2021
🔗 https://t.co/LTQjimh8AQ
2 scroll-timelines, 1 element:
– Fly in from the bottom
– Fly out at the top
*POOF* 🪄🎩🐇 pic.twitter.com/MDJx8O48WK
Unfortunately there’s an issue with the used ScrollTimeline polyfill used, disallowing the combination of two animations. Please to see how this demo behaves.
What’s very crucial here — apart from having non-overlapping Scroll Timelines — is the attaching of the animations. Whereas in the previous demos it had animation-fill-mode: both;
set, this has now been removed. This is a very important thing to do. If you don’t you’ll notice that only the last animation will be applied and might think this is an implementation bug as I did. Thankfully it’s not a bug and was a classic case of PEBKAC.
~
# Horizontal Scroll Section Demo
This demo is based upon this “GSAP ScrollTrigger & Locomotive Scroll” demo by Cameron Knight, which features a horizontal scroll section. I’ve basically left the HTML intact, removed all JS, and added a few CSS Animations + Scroll Timelines to get this working.
See the Pen Scroll-Linked Animations: Horizontal scroll section (@scroll-timeline version) by Bramus (@bramus) on CodePen.
🔥 New #CSS @scroll-timeline demo, in which I have recreated a horizontal scrolling section (and some parallax along with that):https://t.co/dwpzLkAO3V
— Bramus! (@bramus) February 2, 2021
👨🔬 Experimental technology: Chrome Canary with “Experimental Web Platform Features” enabled only for now. pic.twitter.com/ZDfeGYOOJ1
See the Pen Scroll-Linked Animations: Horizontal scroll section (WAAPI / ScrollTimeline version) by Bramus (@bramus)on CodePen.
The tricky part was the horizontal section of course:
- Stretch out the wrapping
#sectionPin
to500vh
so that we create extra room to scroll. -
Set up a
@scroll-timeline
for#sectionPin
while it’s inside entirely covering the scrollport, using the mind-flippingstart 1
→end 1
offset combination.@scroll-timeline horizontal-section-scrolling-into-view { source: selector(body); scroll-offsets: selector(#sectionPin) start 1, /* Start when #sectionPin touches the top edge of the scrollport and is visible inside the scrollport */ selector(#sectionPin) end 1 /* End when #sectionPin touches the bottom edge of the scrollport and is visible inside the scrollport */ : time-range: 1s; }
This weird offset combination only works because
#sectionPin
is bigger than the scrollport. I’ll leave it to you, the reader, to dig into it further 😉 On
.pin-wrap
useposition: sticky;
(so that it remains in view) and translate it horizontally while scrolling.@keyframes move-horizontal-scrolling-section { to { transform: translateX(calc(-100% + 100vw)); /* Move horizontally so that right edge is aligned against the viewport */ } } .pin-wrap { position: sticky; top: 0; animation: 1s linear move-horizontal-scrolling-section forwards; animation-timeline: horizontal-section-scrolling-into-view; }
@scroll-timeline
is tracking #sectionPin
, but the animation is applied to it’s child element .pin-wrap
. This is truly one of the powers of @scroll-timeline
.🐛 Want to dig deeper? Here’s a rendering glitch you might notice:
Upon reversing the animation when scrolling back up, it glitches.
This is a confirmed bug which will hopefully be fixed soon. — Relevant Chromium Bug: 1175289
~
# CoverFlow Demo
Remember CoverFlow from iTunes? Well, here’s a CSS-only version built with @scroll-timeline
! 🎉
See the Pen Pure CSS Coverflow with CSS ScrollTimeline (+ Scroll Snapping) by Bramus (@bramus) on CodePen.
👀 Remember Coverflow? How about a “Pure CSS” version using @scroll-timeline?
— Bramus! (@bramus) February 4, 2021
🔗 https://t.co/xRTSCSiVX7
🧑🔬 Experimental technology: Chrome Canary with “Experimental Web Platform Features” enabled only for now. pic.twitter.com/YTvOmeyi0w
See the Pen Scroll-Linked Animations: Coverflow (JS WAAPI + ScrollTimeline version) by Bramus (@bramus) on CodePen.
Looking under hood, here’s how it’s structured:
- The
<ul>
element is the scroll container, and the<li>
elements inside scroll. - The
<li>
elements themselves switch z-index, and their contained<img />
elements are transformed.
That 2nd thing is quite key here: If we were to transform the <li>
elements the scroll-container’s width would change. This would make the scroll-linked animation recalculate at every change, resulting in a flickering animation. We don’t want that of course.
💿 Album covers in this demo come from the wonderful Loci Records label. You should definitely check them out. Their “Season Two” compilation is a good start: https://locirecords.com/season-two/
🐛 In this demo you’ll notice the native ScrollTimeline implementation in Chromium being buggy. Click for more details/info.
If you have “Experimental Web Platform Features” enabled you’ll notice two bugs in this demo:
- The
z-index
is not always applied correctly (slight flicker). - (Not shown in video above) Elements at the very start over very end animate “too late”/”too soon”
You can see this second issue in the recording below:
On load card_0
and its siblings start at 0%
animation progress, no matter what their position inside the scroll-container. When scrolling horizontally you see the first few items “catch up” with their animation state. By hitting card_5
the animation renders as expected: the item shown in the middle is at animation progress 50%
. You can this very same wrong behavior again when closing in on the right edge: the last 5 items have the same issue (but in reverse). By the time the last card is in the center, its animation progress is 100%
, whereas it should be at 50%
.
This debug session shows best:
For reference, in a non-buggy implementation the initial rendering would show card_0
at 50%
animation progress, as it’s positioned halfway the scrollport:
Relevant Chromium Bug: 1174838
~
# Stacking Cards Demo
In this demo I tried recreating this Stacking Cards demo from CodyHouse, initially by Claudia Romano.
See the Pen 🌟 Stacking Cards, Final Version by Bramus (@bramus) on CodePen.
🥳🥳 Aha! Found it! Got my `position: sticky` working.
— Bramus! (@bramus) February 16, 2021
1️⃣ Don't vary `top` per sticky items, but fixate it to 0 and adjust the padding to offset 'm
2️⃣ Lay out all cards in their wrapper using CSS Grid and fixated rows. Their padding simply bleeds out (huh? 🤯) pic.twitter.com/2V7b8vyKbV
Thanks to playing with animation-delay
I’m able to use one shared @scroll-timeline
for each card
:root {
--numcards: 4;
}
#card_1 { --index: 1; }
#card_2 { --index: 2; }
#card_3 { --index: 3; }
#card_4 { --index: 4; }
@scroll-timeline cards-element-scrolls-in-body {
source: selector(body);
scroll-offsets:
selector(#cards) start 1, /* Start when the start edge touches the top of the scrollport */
selector(#cards) start 0 /* End when the start edge touches the start of the scrollport */
;
time-range: 4s;
}
.card {
--index0: calc(var(--index) - 1); /* 0-based index */
--reverse-index: calc(var(--numcards) - var(--index0)); /* reverse index */
--reverse-index0: calc(var(--reverse-index) - 1); /* 0-based reverse index */
}
@keyframes scale {
to {
transform: scale(calc(1.1 - calc(0.1 * var(--reverse-index))));
}
}
.card__content {
transform-origin: 50% 0%;
will-change: transform;
--duration: calc(var(--reverse-index0) * 1s);
--delay: calc(var(--index0) * 1s);
animation: var(--duration) linear scale var(--delay) forwards;
animation-timeline: cards-element-scrolls-in-body;
}
At first I struggled a lot with getting the sticky part right, as my position: sticky;
would work as expected, but not as I wanted: the last card slid over the preceding ones:
After doing a detour with manually trying to translate the cards, I eventually found how to get my position: sticky;
to work as I wanted.
- Don’t vary
top
by an extra1em
per sticky item, but fixatetop: 0;
and adjust thepadding-top
to achieve the offset. - Lay out all cards in their wrapper using CSS Grid with fixated rows. Their padding simply bleeds out (huh? 🤯), and therefore they will be evenly spaced using
gap
.
Cool part is: browsers that don’t understand @scroll-timeline
but do speak position: sticky;
will also see the effect, but simply without the scaling.
~
# In Closing
With those fine demos we conclude this second part of this series! We’ve covered how to create Scroll-Linked Animations based on the location of an element within the scroller, and how we can tweak their offsets. I think it’s pretty amazing what we can do with them … the amount of JavaScript that can be replaced with it will be huge.
I hope I’ve been able to get you excited for this possible future addition to CSS throughout this post. Although it still is in its very early stages, I’m confident this will become a CSS WG Recommendation one day 🙂
I’m glad to see that the Chromium engineers are actively working on this experimental implementation, taking the time to respond to newly reported bugs. I hope that other browser vendors will follow suit soon. Relevant tracking bugs to flag/star/follow:
- Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=1023424
- Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1676780
- Safari: https://bugs.webkit.org/show_bug.cgi?id=222295
🗃 You can find all demos shown in this post over at CodePen, in a Collection Scroll-Linked Animations: Part 2. It’d be great if you could ❤️ the collection and/or the demos you like.
~
To help spread the contents of this post, feel free to retweet its announcement tweet:
🔥 The future of CSS: Scroll-Linked Animations (Part 2)
— Bram.us (@bramusblog) March 3, 2021
In this 2nd part covering @scroll-timeline we turn things up a notch and dig into creating Scroll-Linked Animations using Element-based Offsets
🔗 https://t.co/OzatNnS48l#CSS #ScrollTimeline #animation pic.twitter.com/IIwaDHCEii
Follow @bramus (= me, the author) and/or @bramusblog (= the feed of this blog) on Twitter to stay-up-to date with future posts. RSS also available.
~
Thank me with a coffee.
I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
Leave a comment