5

Scroll-Driven Animations: You want overflow: clip, not overflow: hidden

 6 months ago
source link: https://www.bram.us/2024/02/14/scroll-driven-animations-you-want-overflow-clip-not-overflow-hidden/?ref=sidebar
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Scroll-Driven Animations Skip to content

css-overflow-clip.png

Because overflow: hidden creates a scroll container it can interfere with the Scroll-Driven Animations scroller lookup mechanism. The fix is to use overflow: clip instead.

Scroll-Driven Animations

At its core, creating a Scroll-Driven Animation is pretty easy. Take an existing CSS Animation or WAAPI Animation, connect it to a ScrollTimeline or ViewTimeline, and you’re done.

In CSS, you do this using the animation-timeline property:

#target {
  animation: fade linear forward;
  animation-timeline: scroll();
}

The scroll() function – or scroll(nearest) if you want to be more explicit about it – will look up the nearest ancestor scroller, and use its scroll position that to drive the animation.

Most of the times that works as expected, but sometimes it doesn’t do anything. The culprit: an overflow: hidden sitting somewhere in between the target and the scroller.

👨‍🏫 New to learn more about Scroll-Driven Animations and want to learn more? Go check out scroll-driven-animations.style to learn all about it.

The problem with overflow: hidden

The overflow property defines what should happen when content doesn’t fit in the parent element box. Its initial value is visible, which forms the source material for the “CSS is awesome” meme:

css-is-awesome.jpg

To visually hide all the content that overflows, you can set overflow to hidden. But! Doing that comes with a caveat: when you set overflow: hidden, it also creates a scroll container.

As per spec:

This value indicates that the box’s content is clipped to its padding box and that the UA must not provide any scrolling user interface to view the content outside the clipping region, nor allow scrolling by direct intervention of the user […]. However, the content must still be scrollable programmatically […] and the box is therefore still a scroll container.

The creation of a scroll container is what trips up the scroll(nearest) lookup mechanism. In the snippet below scroll() won’t find the #scroller but the #intermediate element with the overflow: hidden applied to it instead. Uhoh!

<div id="scroller" style="overflow: scroll;">
     <div id="intermediate" style="overflow: hidden">
        <div id="target" style="animation-timeline: scroll()">
            …
        </div>
    </div>
</div>
❌ Problematic code example

overflow: clip to the rescue!

You could try and work your way out of the problem caused by overflow: hidden by refactoring your code to use a named Scroll Timeline. Honestly though, that’s a lot of work.

Thankfully there is alternative solution which is much more more easy: use overflow: clip. overflow: clip works exactly the same as overflow: hidden, except for the fact that overflow: clip does not create a scroll container.

As per spec:

[…] unlike overflow: hidden which still allows programmatic scrolling, overflow: clip forbids scrolling entirely, through any mechanism, and therefore the box is not a scroll container.

And with that, the example below will work as initially expected: the #target element will use the #scroller element’s scroller to drive the animation.

<div id="scroller" style="overflow: scroll;">
     <div id="intermediate" style="overflow: clip">
        <div id="target" style="animation-timeline: scroll()">
            …
        </div>
    </div>
</div>
✅ Fixed code example

☝️ Additionally, using overflow: clip also allows you to use overflow-clip-margin to determine how far outside its bounds an element may be painted.

Embedded below is a demo that demonstrates all this. On the left is a (red) box inside a wrapper that has overflow: hidden applied to it. On the right the wrapper around the (green) box has overflow: clip applied to it.

The (red) box on the left is not able to find the root scroller to drive its animation, but the (green) box on the right does.

In closing

I see no reason to use overflow: hidden at all on your web pages, unless you have a good reason to. overflow: clip has exactly the same outcome, doesn’t interfere with Scroll-Driven Animations, and has great browser support:

overflow-clip.png
Screenshot of overflow: clip support on CanIUse

# Spread the word

To help spread the contents of this post, feel free to retweet the announcements made on social media:

Posted byBramus!February 14, 2024February 16, 2024Posted inOriginal ContentTags: css, overflow, scroll-driven animations

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …) View more posts

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK