Summary: | iPadOS: Viewport doesn't correctly restore after dismissing software keyboard for installed web apps | ||||||
---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | ik | ||||
Component: | Layout and Rendering | Assignee: | Nobody <webkit-unassigned> | ||||
Status: | NEW --- | ||||||
Severity: | Normal | CC: | bfulgham, formularsumo, megan_gardner, philipp.pirrung+apple, simon.fraser, tomac, webkit-bug-importer, wenson_hsieh, zalan | ||||
Priority: | P2 | Keywords: | InRadar | ||||
Version: | Safari 16 | ||||||
Hardware: | iPhone / iPad | ||||||
OS: | iOS 16 | ||||||
Attachments: |
|
Description
ik
2023-04-01 01:21:32 PDT
A couple of other/additional observations, maybe this will help or they may be separate issues (let me know plz) I've managed to mostly work around the issue by using the Visual Viewport API and resize the html and body via javascript. Weird thing is that I have to (re)register the listener every time the input is focused or it won't fire more than once: 1. On input focus: add a visualViewport 'resize' listener (it will fire almost immediately) 2. In the resize listener, set the height of html and body to match visualViewport.height, then scroll both to '0'. 3. On input blur: unregister the 'resize' listener and unset html and body height, then scroll both to '0' The second thing I found out is that the document loses focus when I dismiss the keyboard using the dedicated button, at least according to the page lifecycle library I use (https://github.com/GoogleChromeLabs/page-lifecycle). This doesn't happen on iPhone, just on iPad (Mini, again, I don't have other devices to test this with). Scrolling doesn't re-focus it, I have to really tap something. I can confirm that this issue exists on iPad Pro (11-inch) (3rd generation) with iPadOS 16.3.1. Furthermore I was able to work around this behaviour with the following: window.visualViewport.addEventListener("resize", () => { window.requestAnimationFrame(() => { if (window.visualViewport.height == document.documentElement.getBoundingClientRect().height) { document.documentElement.scrollTop = 0; } }); }); It seems that setting the scrollTop after the resize has finished, updates the visualViewport. Checking if the height of the visualViewport matches the height of the document ensures that the scrollTop is only "updated" when the full screen is available again (i.e. the keyboard has been dismissed). While I'm in no way happy with this work-around, it seems to fix the originally described behaviour in all use-cases I've tested. Just wanted to add to philipp's comment (#3): One important thing to note here is that the rAF() is needed because the viewport resize event can fire before the visualViewport.height reflects the new height. I can't test right now, but I remember that the behavior was different between regular Safari and installed web apps; one of them seemed to always work as expected without rAF(), the other needed it. So instead of this: ``` visualViewport.addEventListener('resize', () => { console.log( visualViewport.height ); }); ``` You need this: ``` visualViewport.addEventListener('resize', () => { requestAnimationFrame( () => { console.log( visualViewport.height ); }); }); ``` I'll try to find some time to file a separate bug for this but if someone beats me to it: please do :)) Just wanted to add that this is an issue I've experienced before in the Whatsapp PWA (Web App), on an iPad Air 3 (2019) running iOS 17.6. |