w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 666 forks source link

[cssom-view] scrollIntoView and sticky elements #3104

Open ExtAnimal opened 6 years ago

ExtAnimal commented 6 years ago

Currently the specification at https://drafts.csswg.org/cssom-view/#dom-element-scrollintoview makes no mention of sticky elements.

Chrome appears to behave as expected when there are sticky ancestors of the element being scrolled into view.

But the behaviour needs to be defined.

jonjohnjohnson commented 6 years ago

https://github.com/w3c/csswg-drafts/issues/1459 Related? Or possible dup?

ExtAnimal commented 6 years ago

Tangentially related. #1459 is about scrolling sticky elements.

I'm talking about scrolling a regular element into view which has sticky ancestors which may, when the element is scrolled into view, reduce the scrolling area viewport.

It's a difficult one. Because if there's a top:0 sticky element, then that definitely shrinks the viewport. But what if it's a weird one like top: 5px? or top: 50%? There may be multiple stickies occluding the viewport, creating multiple areas which could be zones for scrolling into view.

It's so weird that behaviour has to be strictly defined, otherwise different browser vendors will do all kinds of different things.

jonjohnjohnson commented 6 years ago

An ancestor of the element being scrolled into view is sticky? Or does the resolution in https://github.com/w3c/csswg-drafts/issues/2929 relate? Different browsers are already applying heuristics to fixed and sticky positioned elements as well as are now s'pose to take the scroll-padding property into account. Maybe a test case would help communicate your concern?

emilio commented 6 years ago

Could you post a test-case which differs across browsers? (We should define the behavior regardless, but that makes it easier to evaluate which definition we want :)).

Thanks!

jonjohnjohnson commented 6 years ago

@ExtAnimal Here is a crude (starting point) attempt at a test case for this issue. Though consistent across browsers, it shows how sticky elements obfuscate an element using both scrollIntoView as well as scrolling to IDs via anchors.

http://jsfiddle.net/8hjtwecb/

I understand that the use of scroll-padding fixes this issue quite well in regards to elements with position: fixed, but doesn't exactly help when using position: sticky because an elements perceived scrollport is different when sticky elements are "stuck" or not.

ExtAnimal commented 5 months ago

@emilio The example above shows the issue. Scrolling id1 into view places id1 below the .sticky element. It's not* in view.

When calculating a target rectangle into which an element may be scrolled, the rectangles of occluding sticky elements must be subtracted from that rectangle.

And there may be multiple target rectangles if some sticky elements are for example top : 50%. There may be then two target rectangles. Any algorithm the standard proposes should select the largest unoccluded rectangle.

emilio commented 5 months ago

"Occluded" is fairly hard to define as a concept, fwiw. Do things like box shadows count as "occluding"? See also all the ink-overflow-related discussions.

In general, scrollIntoView also doesn't account for overlaid abspos elements or fixed-pos elements, that's what scroll-{padding,margin} are for, generally. It also doesn't account for z-index, and a lot of other things that it could maybe account for.

Not opposed to add some best-effort handling of sticky to the scrollIntoView algorithm, but my ask was to see what different browsers were doing. At least on my machine, the test-case above behaves consistently across browsers, so there's no "magic" going on.

A concrete proposal would be great. I could try to come up with something and tests, but honestly I'm a bit swamped with other work right now and this doesn't seem like something super-prioritary...

ExtAnimal commented 5 months ago

position:absolute elements are irrelevant. They float above the layout and occlude no matter what. That's expected.

box-shadow is also irrelevant.

All that has to be taken into account is the boundingClientRect of position:sticky elements.

A simplified best-effort could even only consider position:sticky elements which are attached to the edges of the scrolling viewport. for example with top or bottom or right or left <= 0.

This is the most common usage. To "stick" headers or footers to the edges of a scrolling viewport.

If we handled that simplified scenario, it's just a matter of clipping off those stickies when calculating the rectangle to move the scrolled element into.