Bug 170280 - Dynamically added position:fixed element is in the wrong place
Summary: Dynamically added position:fixed element is in the wrong place
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: Safari 10
Hardware: iPhone / iPad iOS 10
: P2 Normal
Assignee: Simon Fraser (smfr)
Keywords: InRadar
: 171413 (view as bug list)
Depends on:
Reported: 2017-03-30 04:18 PDT by Wart Claes
Modified: 2017-05-02 23:08 PDT (History)
6 users (show)

See Also:

Simple testcase (2.06 KB, text/html)
2017-05-01 15:56 PDT, Simon Fraser (smfr)
no flags Details
Patch (6.38 KB, patch)
2017-05-02 15:21 PDT, Simon Fraser (smfr)
thorton: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Wart Claes 2017-03-30 04:18:25 PDT
On a page with a fixed positioned element in WKWebView renders the element on the wrong place.

This occurs when the element is shown after a user interaction. The element is positioned lower then it should be. This only happens on iOS 10.3 (Safari 10.1). 

The bug was tested on iPhone 5s and iPhone 7.

Link to the github repository https://github.com/WartClaes/ios10.3-bug/tree/master with a simple test case. 
Link to the demo page http://trbo.be/ios/

# Steps to reproduce
1. On initial load, scroll down so the button is in the middle of the screen
2. Click the button
3. The fixed header is now shown somewhere on the page, but not in it’s intended position
4. If you want to select the text “header”, you can notice that the actual element is still on top where it should be, it is just painted in the wrong place
Comment 1 Alexey Proskuryakov 2017-03-31 11:04:25 PDT
Comment 2 Wart Claes 2017-04-18 01:54:27 PDT
Is there any more information about this one?
Comment 3 Simon Fraser (smfr) 2017-05-01 15:25:44 PDT
Seems similar to bug 171413: both use nested position fixed.

It's pretty odd that you're making <body> position:fixed with a negative top here.
Comment 4 Simon Fraser (smfr) 2017-05-01 15:56:07 PDT
Created attachment 308781 [details]
Simple testcase
Comment 5 Simon Fraser (smfr) 2017-05-01 22:03:30 PDT
This only happens with UI-side compositing, and reproduces on Mac too in that configuration.

What's happening is this:

The <header> initially is the only fixed element. Its GraphicsLayer gets a position of 0,10. When you scroll, the scrolling tree calls GraphicsLayerCA::syncPosition() which sets various new positions to make fixed position work. However, these positions don't get into PlatformCALayerRemote (they don't need to).

When the body becomes fixed, <header> is now parented in another fixed element, so we stop tracking it in the scrolling tree. When we do layout for this change, <header>'s GraphicsLayer gets a setPosition({0, 10}) which is pushed to PlatformCALayerRemote during the flush, but PlatformCALayerRemote doesn't see this as a change (it still has {0,10}) so this change doesn't make it to the UI process, and the UI layer remains with its old scroll-influenced offset.
Comment 6 Simon Fraser (smfr) 2017-05-02 14:11:03 PDT
This also only happens if you have margin:0 on the body.
Comment 7 Simon Fraser (smfr) 2017-05-02 15:21:33 PDT
Created attachment 308857 [details]
Comment 8 Tim Horton 2017-05-02 15:45:35 PDT
Comment on attachment 308857 [details]

View in context: https://bugs.webkit.org/attachment.cgi?id=308857&action=review

> Source/WebKit2/ChangeLog:9
> +        Layers for position:fixed elements are have their positions reconciled after scrolls

are have their?
Comment 9 Simon Fraser (smfr) 2017-05-02 16:01:04 PDT
*** Bug 171413 has been marked as a duplicate of this bug. ***
Comment 10 Simon Fraser (smfr) 2017-05-02 16:08:27 PDT
Comment 11 Wart Claes 2017-05-02 23:08:18 PDT
thanks Simon and Tim!
Comment 12 Wart Claes 2017-05-02 23:08:23 PDT
thanks Simon and Tim!