position sticky renders incorrectly when it contains a transformed absolute element
Reported by
mich...@maestrooo.com,
Dec 3 2016
|
||||||
Issue descriptionUserAgent: 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
,
Dec 4 2016
Rob: you've done some work on position:sticky. Could you please take a look?
,
Dec 9 2016
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
,
Dec 13 2016
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.
,
Dec 13 2016
,
Dec 13 2016
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.
,
Dec 13 2016
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
,
Jan 17 2017
Looks like this bug has the same root cause as another one I started a patch for. |
||||||
►
Sign in to add a comment |
||||||
Comment 1 by loyso@chromium.org
, Dec 4 2016Status: Assigned (was: Unconfirmed)