New issue
Advanced search Search tips

Issue 841432 link

Starred by 2 users

Issue metadata

Status: Started
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug



Sign in to add a comment

[css-position-sticky] overconstrained sticky position interop issue with safari

Reported by h...@jonjohnjohnson.com, May 9 2018

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3404.0 Safari/537.36

Steps to reproduce the problem:
1. Open testcase -> http://output.jsbin.com/qunekib/3
2. Scroll down, notice the "panel-by-panel" scrolling
3. Reach scroll position where panel #10 should scroll in and sit at bottom edge.
4. Panels #10 to #14 don't move/position according to bottom/top box offset values, like previous panels, they are the last 4, which is the amount of "nesting" used to show edges of panels with normal scrolling mechanism. These panels stick to top edge once reaching the scrolling end.
5. Open Safari and follow steps, noticing how top/bottom are respected all the way through.

What is the expected behavior?
When opposing box offsets do not conflict on a sticky positioned element, they should respect both offsets values. Like what is happening in Safari.

What went wrong?
Incorrect position of sticky elements when "perceived" conflicts in box offsets

Did this work before? No 

Does this work in other browsers? Yes

Chrome version: 68.0.3404.0  Channel: n/a
OS Version: OS X 10.12.6
Flash Version: 

This also "works" in Firefox, though, rendering mid scroll flickers, even if they position elements correctly once scrolling concludes.
 
Labels: Needs-Triage-M68
Labels: Hotlist-Input-Dev
Owner: flackr@chromium.org
Status: Assigned (was: Unconfirmed)
I can also reproduce this. flackr@ do you know what might have caused this?
As a side note, opposing box offsets have interop issues in general (not related to nesting) shown here...

http://output.jsbin.com/zuwikov/

Left side shows blocks trying to stick to top and bottom. Right side shows normal flow position. View in chrome versus safari.

There is somewhat of an issue filed with the csswg about implementation and interop versus spec language for conflicting box offsets. https://github.com/w3c/csswg-drafts/issues/1294
Cc: smcgruer@chromium.org
This is a very complex setup, I'm still trying to figure out how the 8 nested sticky elements are supposed to work together to produce the result and why the 10th one is different.

You seem to have identified the underlying issue to be the resolution of conflicting box offsets which do not actually conflict, is it possible to make a simple test case of this issue?
This surely is a very complex setup, but when it becomes simpler, the conflicts disappear. As in, if the nesting of the "stack" of panels is not as deep, say 3 levels, then there is no conflict when offsetting the sticky positioning to reach the other end of the stack.

I'll try to create a video showing how to reason about the DOM and utility classes in the example, and create outlines for each of the sticky elements to more easily visualize the conflicting boundaries. 
flackr@chromium.org I attached an altered testcase that highlights a bit more of what's going on faking the scrollers box with the nested sticking offsets. Also added red markers to show how the offsets move. It is easier to see the difference in behavior between safari and chrome when loaded up side by side seeing the marker movements, which traverse the dom right to left.
nestedstickytopbottom.html
19.8 KB View Download
Thanks! This is very helpful. But the thing that it's pointed out to me is that on #10 and later, the 4th nested .page-offset has different styles for top and bottom which is causing the incorrect behavior, matched by:

.scrollport--2 .page:nth-last-child(-n + 2) [class^="page-offset"], .scrollport--3 .page:nth-last-child(-n + 3) [class^="page-offset"], .scrollport--4 .page:nth-last-child(-n + 4) [class^="page-offset"], .scrollport--5 .page:nth-last-child(-n + 5) [class^="page-offset"], .scrollport--6 .page:nth-last-child(-n + 6) [class^="page-offset"], .scrollport--7 .page:nth-last-child(-n + 7) [class^="page-offset"], .scrollport--8 .page:nth-last-child(-n + 8) [class^="page-offset"]
  bottom is calc(((var(--depth) - var(--dive) - var(--endOffset, 0)) * var(--gap)) + (var(--depth) * var(--page)) - ((var(--depth) - var(--dive)) * var(--page)))

.scrollport--2 .page:nth-last-child(-n + 2) [class^="page-offset"], .scrollport--3 .page:nth-last-child(-n + 3) [class^="page-offset"], .scrollport--4 .page:nth-last-child(-n + 4) [class^="page-offset"], .scrollport--5 .page:nth-last-child(-n + 5) [class^="page-offset"], .scrollport--6 .page:nth-last-child(-n + 6) [class^="page-offset"], .scrollport--7 .page:nth-last-child(-n + 7) [class^="page-offset"], .scrollport--8 .page:nth-last-child(-n + 8) [class^="page-offset"]
  top is calc(((var(--dive) - 1) * var(--page)) + (var(--gap) * var(--indexRev, 0)))

If you change bottom to calc(((var(--depth) - var(--dive)) * var(--gap)) + (var(--depth) * var(--page)) - ((var(--depth) - var(--dive)) * var(--page)))
and top to 0
which the simple rules on #9 and earlier, this works correctly.

I'm guessing the fact that it matches this complex selector is somehow unique to chrome and not safari?
Hey flackr@chromium.org, your suggested fix/edits do in fact make both safari and chrome behave the same, but you lose the visuals of reaching the end of the "stack" that safari does in fact support. Load up the test case without your edits and see how you lose that scrollend/top stacking visual in both safari as well as chrome. This is the key factor.

Comment 9 Deleted

At the 4th second in the video, the pages stack up at the top of the scrollbox? This is what both chrome and safari allow. But when chrome allows this top sticking for the last set of pages, it breaks the bottom sticking boundaries for each of those pages offsets for how they are positioned as they start to scroll in.

http://cl.ly/szXQ

If you load the test case up in chrome and safari, side by side, you can see the red line visuals differing behavior in the last 5 pages of the stack scroll into view.
Thanks for the explanation, this makes sense. I'll look into this tomorrow. I now know exactly which element has gotten the wrong position, so it should be easy to debug exactly why it's gotten the incorrect sticky offset and hopefully get to the bottom of this issue. It seems wrong that the non-zero top offset would push that element down before it has even scrolled into view - let alone anywhere near the top of the viewport.

Comment 12 Deleted

Cc: flackr@chromium.org
Components: -Blink>Scroll Blink>Layout
Labels: -Hotlist-Input-Dev -OS-Mac
Owner: e...@chromium.org
Summary: [css-position-sticky] overconstrained sticky positioned block in flex layout interop issue with safari (was: [css-position-sticky] Nested sticky positioned blocks (w/ shared containing block) use of opposing box offsets interop with safari)
So the sticky offset of the particular container element in question (i.e. document.querySelector('.page:nth-child(10) .page-offset---') ) is initially 0, it is in fact getting its offset of 60px from the flex layout of its parent item.

I started focusing on this difference in layout and reduced the testcase to a pretty minimal example. I believe this to be a layout compat issue with flex + overconstrained sticky. Over to layout team to triage.
reduced-flex-sticky.html
714 bytes View Download
Sorry that my initial testcase is so complex, but from what I've seen, it's not related to display flex. Attached is a quick (and dirty) non-flex (spoofing the vertical centering that flex allowed with pseudo elements) version of my original testcase. It still has the issue, when reaching the 10th page (and last pages which have both top and bottom offsets not set to auto), of being positioned incorrectly when compared to safari. Check the testcase in both browsers and see the issue and that flex containers are not being used.

Thanks for all your help flackr@chromium.org
nestedstickytopbottomsansflex.html
20.3 KB View Download
Cc: -flackr@chromium.org
Owner: flackr@chromium.org
Right, I thought through this use case some more and I'm pretty sure it comes down to the difference of Safari obeying the bottom constraint over the top, and Chrome and Firefox preferring the top over the bottom. See for example this case: http://output.jsbin.com/xigoges or http://jsbin.com/buzesud/edit?html,css,js,output

Confusingly, we seemed to have recorded that Safari preferred the top on https://github.com/w3c/csswg-drafts/issues/1294 but this doesn't seem to be the case.

I also don't observe this behaving correctly in firefox, even the original demo (http://output.jsbin.com/qunekib/3) seems to immediately stack at the top of the browser whereas Chrome and Safari stack at the bottom and when you reach the bottom the topmost visible card continues to slide up.
I mentioned that github issue in my first comment here. And within that issue, I commented further down the thread, recording each browsers differences when "overconstrained" edges (https://github.com/w3c/csswg-drafts/issues/1294#issuecomment-373514495).

Safari uses both simultaneously, and averages the difference as you scroll through the conflicting in-flow position (see in safari -> http://output.jsbin.com/zuwikov/).

But in this example, I don't think chrome us just preferring the top over bottom. From watching the scrolling within the second testcase I attached, you see the offset box visuals not being in conflict. See how that case doesn't show safari "averaging" the offsets during scroll.

When I test all these testcases in Firefox, they behave like safari. They just drop frames and often need text highlighting of dom to cause a repaint, where the offsets show correctly. I do have firefox "WebRender" enabled which, I believe allows for the parity with safari (https://bugzilla.mozilla.org/show_bug.cgi?id=1456938#c1).
Just checked again and see that firefox 63.0a1 (2018-07-16) (64-bit) does in fact treat sticky positioning the same as safari. It just has poor rendering even when enabling webRender.
Status: Started (was: Assigned)
Summary: [css-position-sticky] overconstrained sticky position interop issue with safari (was: [css-position-sticky] overconstrained sticky positioned block in flex layout interop issue with safari)
Re #17, apologies it was just due to my old version of firefox that I was seeing old behavior. If Firefox and Safari are aligned on splitting the conflict we can align on this behavior as well though I hope we can get this behavior written in the spec.
flackr@chromium.org again, thanks for all your time and insight.

Though firefox and safari have parity for the original testcase(s), it doesn't actually "split the conflict" as you say. In my example from the github issue I referenced in #16, a simpler (non-nested and non-shared containing block) http://output.jsbin.com/zuwikov/ example. It highlights how firefox and chrome do not split the conflict. But again, the original testcase here doesn't actually have a box offset conflict to split. For some reason chrome thinks there is a conflict that isn't there?
flackr@chromium.org, here is a real example of opposite offsets conflicting: http://jsfiddle.net/78oamb6u/53/

In it, you can open it up and see how safari is the only browser that allows both to affect the position. Firefox uses top, as does chrome, but they handle margins a bit different when creating the height of the "scrollbox"?

In my original nested sticky position example, both firefox and safari "sequentially" move the sticking boxes around, but again, that example doesn't seem to have conflicting box offset values, though something in chrome thinks the values conflict.

Sign in to add a comment