Skip to content

Instantly share code, notes, and snippets.

@Reinmar
Last active March 19, 2020 10:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Reinmar/91c70d2882523f47da7c498050421204 to your computer and use it in GitHub Desktop.
Save Reinmar/91c70d2882523f47da7c498050421204 to your computer and use it in GitHub Desktop.

Bug report for Safari@iOS's viewport mechanics when the software keyboard is visible

Issue: https://bugs.webkit.org/show_bug.cgi?id=191204

Introduction

The behaviour of the Safari@iOS's viewport makes it very hard to position anything reliably when the software keyboard is visible.

We're dealing with this problem in CKEditor 5, but I see that other rich-text editor have similar problems. I haven't yet seen a rich-text editor which would work well on Safari@iOS (in fact, some of them hide their samples when visiting from Safari@iOS – perhaps to not scare people away ;)). And people have really spent a lot of time on this.

So, the problem is that when the software keyboard appears the following three things stop working:

  • position:fixed becomes unreliable,
  • window.innerHeight returns a useless value,
  • position:absolute; top: window.scrollY and position:absolute; bottom: -window.scrollY become unreliable too.

Since all of those methods to position something in the viewport fail it's an art to keep things in place. You can try to workaround this by positioning things absolutely and only to the top of the viewport (I saw some apps succeed to keep things there; although, I don't know how). But that's both hacky (special code for mobile Safari only), unstable and it does not resolve all the issues. For instance, sometimes you just need to know the lower boundary of the viewport e.g. to scroll the viewport to the caret.

PS. By "viewport" I mean the part of the screen where I can see the website. This is, the green box in the Chrome@Android's version of this diagram:

diagram showing viewport layers in Safari@iOS and Chrome@Android

Test playgrounds

Fixed positioning

Demo: https://ckeditor5.github.io/misc/viewport-fixed.html

Screenshots from Safari@iOS:

screenshot from Safari@iOS in various scroll positions screenshot from Safari@iOS in various scroll positions screenshot from Safari@iOS in various scroll positions screenshot from Safari@iOS in various scroll positions

Screenshots from Chrome@Android:

screenshot from Chrome@Android in various scroll positions screenshot from Chrome@Android in various scroll positions screenshot from Chrome@Android in various scroll positions screenshot from Chrome@Android in various scroll positions

As you can see, on Android the green and red boxes are always fully visibile. Even when the software keyboard is visible.

window.innerHeight and absolute positioning

Demo: https://ckeditor5.github.io/misc/viewport-absolute.html

Screenshots from Safari@iOS:

screenshot from Safari@iOS in various scroll positions screenshot from Safari@iOS in various scroll positions screenshot from Safari@iOS in various scroll positions screenshot from Safari@iOS in various scroll positions

Screenshots from Chrome@Android:

screenshot from Chrome@Android in various scroll positions screenshot from Chrome@Android in various scroll positions screenshot from Chrome@Android in various scroll positions screenshot from Chrome@Android in various scroll positions

Again, all works as expected on Android and really bad in Safari.

To sum up

The current behaviour of Safari is extremely problematic. I know there must have been some reason for it to be designed this way (with the additional scrollable layer). My guess is – performance. As I understand, there's no "resizing" happening when the keyboard slides up. However, performance is meant to ensure good UX. But right now the UX of all RTEs the I know is just bad (or worse) on Safari because of this behaviour. We've done quite a lot of research on this and failed to find a good solution.

I would also like to point out that the Android's behaviour is the one which was intuitive for me. Since I don't own an Android device myself I've been coding the above samples as I thought they should work and only later on I learnt that they work perfectly fine in Chrome.

Finally, the "scroll to show the caret" problem means that fixing e.g. just position:fixed will not solve all the problems – the window.innerHeight property and window.scrollY will also need to cooperate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment