Skip to content

[cssom-view-1] Clip aligned element box by intermediate scrollers #13411

Open

Description

@flackr

I discovered that we have an interop difference with scroll into view. Consider the following cases:

Demo page

<style>
.scroller { overflow: auto; position: relative; }
#A, #B { position: relative; }
#A { top: -400px; }
#B { top: -10000px; }
</style>
<!-- long scrollable content -->
<div class=scroller>
  <div id="A">partially in view</div>
  <div id="B">completely above scroller</div>
</div>

Scrolling to #A, Since this patch in 2016, blink has clipped the rect we scroll into view to the portion that can be made visible in the inner scroller, and then scrolled the outer scroller to that clipped rect. gecko and webkit scroll to the original element bounds even though this aligns a portion of the element that can't be seen.

Image

Scrolling to #B however still scrolls to the element's box.

I think chromium's behavior for #A is good, and I have landed similar related expectations in wpt for scroll margin: https://wpt.live/css/css-scroll-snap/scroll-margin-overflow-ancestor.html

I think for #B, we should probably also clip and align the top of the scroll container (top in this case because the element is above the top), i.e. the following:

Image

TLDR; I propose we modify the scroll a target into view algorithm when we finish scrolling in an inner scroll container to clip the target element rect to the visible area in that scroll container. Limit this to scroll containers, i.e. still scroll to clipped element bounds whether clipped by overflow: clip; or clip-path or other mechanisms.

Activity

  1. css-meeting-bot commented on Apr 29, 2026

    @css-meeting-bot
    Member

    The CSS Working Group just discussed [cssom-view-1] Clip aligned element box by intermediate scrollers, and agreed to the following:

    • RESOLVED: scrollIntoView() targets the element's area as clamped by intervening scroll containers
    • RESOLVED: scroll-padding is only taken into consideration on the scroller being scrolled (not on intervening scrollers)
    • RESOLVED: scroll-margin is applied to the clamped area (is not itself clamped)
    The full IRC log of that discussion <fantasai> scribe+
    <fantasai> flackr: Differences in behavior when scrolling into view.
    <fantasai> flackr: Historically, would scroll "into view" regardless of clipping
    <fantasai> flackr: Chrome changed to scroll to the portion that was visible if it's clipped
    <fantasai> flackr: But if it was wholly invisible, it'll scroll to its actual position which is nonsense
    <emilio> q+
    <fantasai> flackr: I think when we perform scrollIntoView(), clip the region to the portion of the element that is not clipped by the outer scroller
    <fantasai> flackr: So you won't scroll to invisible spaces where the box occupies but is not visible to the user.
    <fantasai> astearns: Would this change Chrome's behavior, or new thing?
    <fantasai> flackr: Chrome does it some of the time, but not always.
    <fantasai> flackr: I'm proposing to do it always.
    <astearns> ack emilio
    <fantasai> emilio: I think that's fine.
    <fantasai> emilio: In the issue you mentioned clip-path, I suspect we don't want to do that.
    <fantasai> flackr: Agree we don't want to do that.
    <fantasai> emilio: My concern is things like, if an anchor is off-screen but in-position vertically ...
    <fantasai> emilio: Maybe people use that to anchor scroll positions, and presumably we don't want to scroll that into view...? But maybe scrolling vertically makes sense?
    <fantasai> flackr: Even if the visible box becomes zero area, it still has dimensions of top and bottom which would give you the correct vertical position.
    <fantasai> emilio: Ah, so you want to do this per-axis.
    <fantasai> flackr: I was imagining we want to scroll as close as we can to the visible part of the element, but not so far that we leave the scroller that's clipping it.
    <fantasai> emilio: So wouldn't change behavior for anchors.
    <fantasai> emilio: Slight concern about that, but overall makes sense.
    <fantasai> fantasai: Wrt 'overflow: clip' I would suggest to keep it in sync with 'overflow: hidden' rather than 'clip-path' as you suggested, flackrr.
    <fantasai> flackr: We could do this. My rationale for ignoring 'overflow: clip' is that it's not a scroll container. And we usually don't pay attention to non scroll-containers when walking the ancestors.
    <emilio> I agree with flackr here
    <fantasai> flackr: I always thought about 'overflow: clip' as purely decorative.
    <fantasai> emilio: My mental model was the same
    <fantasai> emilio: 'overflow: clip' is fundamentally not a scroll container, and this is about scroll containers.
    <fantasai> emilio: Becomes a bit weird because there are other things that affect scroll-into-view like scroll-margin etc. and don't affect 'overflow: clip'
    <emilio> q+
    <fantasai> fantasai: I think from author perspective 'overflow' is for containment clipping, and 'clip-path' etc is decorative.
    <astearns> ack fantasai
    <fantasai> fantasai: So although from impl perspective 'overflow: clip' is like 'clip-path', I don't think that's true from authoring perspective.
    <fantasai> flackr: Spec-wise it's pretty different thing.
    <fantasai> flackr: but not opposed.
    <fantasai> emilio: Treating 'overflow: clip' same as scroll ...
    <fantasai> emilio: it gets you into a slipperly slope
    <fantasai> emilio: Should you also inflate/deflate by 'scroll-margin' and 'scroll-padding'?
    <fantasai> emilio: You deflate by that, but it feels weird
    <fantasai> emilio: Treating it as a scroller but without these scrolly things, and then applying overflow-clip-margin on top ...
    <fantasai> flackr: Prefer to start narrow and consider that separately.
    <fantasai> astearns: Distinctions between 'overflow: clip' and 'clip-path'
    <fantasai> astearns: concern is that it would have wider implications?
    <fantasai> fantasai: No
    <fantasai> flackr: Yes. That's the concern.
    <fantasai> fantasai: Happy to split out to separate consideration.
    <fantasai> PROPOSED: scrollIntoView() targets the element's area as clipped by intervening scroll containers
    <fantasai> [tangent wrt scroll-padding etc.]
    <fantasai> emilio: often used for abspos type stuff
    <fantasai> flackr: I think it'll be fine [missed rationale]
    <fantasai> emilio: But doesn't it give you some weird degenerate behavior... it's probably fine
    <fantasai> PROPOSED: scroll-padding is only taken into consideration on the final scroller, and scroll-margin is applied to the clipped region (??)
    <fantasai> astearns: Do we need to clarify that it's clamped if out of region?
    <fantasai> flackr: Yeah we could clarify
    <fantasai> PROPOSED: scrollIntoView() targets the element's area as clamped by intervening scroll containers
    <fantasai> flackr: Inner scroller will use scroll-padding when scrolling
    <emilio> Lgtm
    <fantasai> RESOLVED: scrollIntoView() targets the element's area as clamped by intervening scroll containers
    <fantasai> PROPOSED: scroll-padding is only taken into consideration on the scroller being scrolled
    <fantasai> flackr: scroll-margin should be re-applied to the clipped bounds
    <emilio> Sounds good
    <fantasai> PROPOSED: scroll-padding is only taken into consideration on the scroller being scrolled (not on intervening scrollers)
    <fantasai> RESOLVED: scroll-padding is only taken into consideration on the scroller being scrolled (not on intervening scrollers)
    <fantasai> PROPOSED: scroll-margin is applied to the clamped area (is not itself clamped)
    <fantasai> emilio: Feels a bit weird
    <fantasai> emilio: but maybe it's fine
    <fantasai> flackr: I got some bug reports about this, and in those cases tended to agree.
    <fantasai> flackr: But we can revisit if it seems broken
    <fantasai> RESOLVED: scroll-margin is applied to the clamped area (is not itself clamped)
    <fantasai> astearns: We can revisit if needed
    <fantasai> s/Topic:/Subtopic:/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions