New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 670953 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 670274
Owner:
Closed: Jan 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Chrome , Mac
Pri: 2
Type: Bug



Sign in to add a comment

position sticky renders incorrectly when it contains a transformed absolute element

Reported by mich...@maestrooo.com, Dec 3 2016

Issue description

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

Steps to reproduce the problem:
1. Go to https://jsbin.com/lupinaqeju/edit?html,css,output
2. Scroll into the body

What is the expected behavior?
Normally, the sticky header should display at the top (like all other browser).

What went wrong?
Here, the absolutely positioned element within the sticky element is moved using a transform. While the transformed element should not take space, it does and push the content.

Did this work before? No 

Does this work in other browsers? Yes

Chrome version: 57.0.2939.0  Channel: canary
OS Version: OS X 10.12.1
Flash Version: Shockwave Flash 24.0 r0
 

Comment 1 by loyso@chromium.org, Dec 4 2016

Owner: meade@chromium.org
Status: Assigned (was: Unconfirmed)
Works in Firefox.

Comment 2 by meade@chromium.org, Dec 4 2016

Cc: meade@chromium.org
Owner: flackr@chromium.org
Rob: you've done some work on position:sticky. Could you please take a look?
Labels: OS-Chrome
Owner: smcgruer@chromium.org
Stephen, can you take a look at this? It works when the position is updated on the main thread (i.e. on low dpi devices), but not when it is composited (i.e. on high dpi, with --enable-prefer-compositing-to-lcd-text or by adding will-change as in https://output.jsbin.com/jesuwa ). This means that we must have the wrong offsets in StickyPositionNodeData used by StickyPositionOffset (property_tree.cc).

The constraints in StickyPositionNodeData come from CompositedLayerMapping::updateStickyConstraints and the main_thread_offset comes from Layer::SetPosition and AddTransformNodeIfNeeded https://cs.chromium.org/search/?q=%5C-%5C%3Emain_thread_offset%5C+%3D&sq=package:chromium&type=cs
It certainly appears to be the case that main_thread_offset is not properly offset for the transform.

For the initial unscrolled version of https://output.jsbin.com/mukamiw/6 :

[1:1:1213/115318.981430:INFO:property_tree.cc(355)] Initial scroll position: 0.000000,0.000000
[1:1:1213/115318.981730:INFO:property_tree.cc(363)] Adjusted scroll position by snap, now: 0.000000,0.000000
[1:1:1213/115318.981972:INFO:property_tree.cc(374)] sticky_offset: [8.000000 16.000000]
[1:1:1213/115318.982231:INFO:property_tree.cc(375)] layer_offset: [-1.000000 -200.000000]
[1:1:1213/115318.982504:INFO:property_tree.cc(426)] constraint.is_anchored_top
[1:1:1213/115318.982756:INFO:property_tree.cc(436)] top_limit = 10, top_delta = 0, available_space = 1982
[1:1:1213/115318.983005:INFO:property_tree.cc(440)] sticky_offset is now: [8.000000 16.000000]
[1:1:1213/115318.983271:INFO:property_tree.cc(442)] layer_offset is now: [-1.000000 -200.000000]
[1:1:1213/115318.983525:INFO:property_tree.cc(443)] Returning: [8.000000 16.000000] - [-1.000000 -200.000000] - [0.000000 0.000000] - [8 16] = [1.000000 200.000000]

However the output should be [1, 0] I believe (not sure where the '1' is coming from).

Scrolling a little gives:

[1:1:1213/115422.916643:INFO:property_tree.cc(355)] Initial scroll position: 0.000000,636.000000
[1:1:1213/115422.916912:INFO:property_tree.cc(363)] Adjusted scroll position by snap, now: 0.000000,636.000000
[1:1:1213/115422.917135:INFO:property_tree.cc(374)] sticky_offset: [8.000000 16.000000]
[1:1:1213/115422.917352:INFO:property_tree.cc(375)] layer_offset: [-1.000000 430.000000]
[1:1:1213/115422.917562:INFO:property_tree.cc(426)] constraint.is_anchored_top
[1:1:1213/115422.917756:INFO:property_tree.cc(436)] top_limit = 646, top_delta = 630, available_space = 1982
[1:1:1213/115422.917964:INFO:property_tree.cc(440)] sticky_offset is now: [8.000000 646.000000]
[1:1:1213/115422.918165:INFO:property_tree.cc(442)] layer_offset is now: [-1.000000 430.000000]
[1:1:1213/115422.918357:INFO:property_tree.cc(443)] Returning: [8.000000 646.000000] - [-1.000000 430.000000] - [0.000000 0.000000] - [8 16] = [1.000000 200.000000]

But again this should still be [1, 0] because of the stickiness. So it does look like main_thread_offset should be += [0, 200] which is the Y translate in this example.

I'm looking at SetPosition/AddTransformNodeIfNeeded at the moment, I do not yet understand how to get the transform information to inform the main_thread_offset.
Status: Started (was: Assigned)
Note: making the frame div translate3d(0, -100%, 0); rather than translateY makes the bug disappear, but this is (I think) because the presence of translate3d pushes the frame div into its own cc layer.
Cc: flackr@chromium.org
Status: Assigned (was: Started)
At this point, I'm unsure how to resolve this bug correctly.

In both of Layer::SetPosition and AddTransformNodeIfNeeded the 'position' already includes the translation offset, but we have no way of knowing (as far as I know) what that offset actually was. It appears like the TransformNode is not much help, or I very much misunderstand it :). Without knowledge of what transform was applied, we cannot correct sticky for it.

One possibility would be to promote all transforms who have a stick ancestor, as this would put them in their own layer (much like #6). That feels like an unnecessary layer though.

For now, I'm afraid this will have to wait until flackr@ is back and can educate me more on the sticky

Comment 8 by flackr@chromium.org, Jan 17 2017

Mergedinto: 670274
Status: Duplicate (was: Assigned)
Looks like this bug has the same root cause as another one I started a patch for.

Sign in to add a comment