I have a mobile web app that displays a dialog box within a position: fixed element overlaying the entire screen. No matter how much content is displayed or how far the page has scrolled, the overlay element dims the page content and the dialog appears on top of it all. There is an <input type="search />
field in the dialog.
On Android, when the user taps the input field to give it focus, some pretty erratic behavior often (but not always) ensues:
- The soft keyboard appears, then immediately disappears.
- The underlying page (covered by the overlay) scrolls by a few dozen pixels, sometimes up, sometimes down, sometimes in both directions, and sometimes repeatedly. This also happens when the input field loses focus.
- The overlay element momentarily shifts a few pixels down and right, revealing the underlying content along the top and left edges of the screen. (It returns to place less than a second later.)
This is on Android 2.3.4 with the built-in browser. It may also occur on other Android versions.
The page constructed something like this: (Keep in mind that some of these quirks only show up when the page contains enough content to allow scrolling.)
<head>
<style type="text/css">
#menuoverlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 10;
background-color: rgba(0,0,0,.75);
text-align: center;
}
#menu {
display: inline-block;
margin-top: 1em;
border: 3px solid #02b;
border-radius: 8px;
padding: 1ex;
background-color: black;
color: silver;
}
</style>
</head>
<body>
<div id="menuoverlay">
<div id="menu">
...menu items...
...menu items...
<form action=""><input type="search"/></form>
</div>
</div>
<div id="content">
...lots of stuff...
...lots of stuff...
...lots of stuff...
</div>
<body>
Has anyone else seen this behavior? Have you found a way to prevent it?
Scouring the web led me to a few reports of similar problems. Here's a summary of what I have read so far:
- On many Android devices, the built-in browser apparently does not use WebKit's input fields the way one would expect. Instead, when the html-defined fields gain focus, the browser attempts to cover them with new text widgets that it creates separately.
- These duplicate text fields often ignore css styling, creating an effect where the fields look styled until they gain focus, and then suddenly revert to the system default style.
- The Android browser often fails to position these duplicate fields correctly. When misplaced, they are sometimes visible, but other times only move the focus targets without any visual indication that they have moved.
- These problems often show up when an input field's ancestor element has styles like
transform: translate3d()
,-webkit-backface-visibility
, orposition: fixed
.
Here are some relevant links:
Android Browser textarea scrolls all over the place, is unusable
How can I style an HTML INPUT tag so it maintains CSS when focused on Android 2.2+?
I managed to prevent the momentary overlay shift by setting
outline: none
on myinput
element.I got the wild page scrolling and disappearing keyboard to settle down by setting
overflow: hidden
on the htmlbody
when showing the dialog, and then removing it again when hiding the dialog. This has a nasty side effect of resetting the page's scroll position, so I save it and restore it as necessary, and wrap all this hackery in conditionals so it only runs on Android. (I hope my Android users won't be too distracted when they see the page contents change beneath the semi-transparent overlay while the dialog is open.)Interestingly, I was also able to prevent the wild page scrolling by catching the
touchstart
event on my overlay element and calling preventDefault(). This makes me wonder if all this madness was caused by a sequence of events like this:touchstart
bubbles up to the document roottouchstart
where the duplicate input field was placedI didn't end up catching
touchstart
to solve the problem, because it prevented the input field from gaining focus, and callingfocus()
from javascript just didn't work. I have read that the Android browser disables thefocus()
method on input fields, which would explain this behavior. Perhaps it does this because it wouldn't work with the duplicate text widgets it creates over the html-defined fields.In my case, the "position:fixed;" is not the problem, "vertical-align:center;" or "-webkit-box-align:center;" push back and close the soft keyboard, to use "-webkit-box-align:start;" solved my problem.