in iOS8 using .focus() will show virtual keyboard and scroll page after touch

It looks like you’re definitely hitting an iOS 8 bug. In iOS7, Safari would (apparently) ignore or keep unfocused elements that had focus set prior to page load. This includes both <input autofocus> and input.focus() that occur up to some point, possibly page load (I tested just with an inline script).

In iOS 8, Safari is now apparently remembering that the element was focussed but not actually focussing it until a touch down event. It is then blindly sending a click event to whichever element received the touch up.

Both browsers behave the same for input.focus() occurring after page load. They both zoom to the element and bring up the keyboard.

Tests:

  • input.focus() before page load: http://fiddle.jshell.net/qo6ctnLz/3/show/
  • <input autofocus>: http://fiddle.jshell.net/qo6ctnLz/4/show/
  • input.focus() after page load: http://fiddle.jshell.net/qo6ctnLz/6/show/

The good news is that you only need to be worried about new behavior on elements you want to prefocus. The other good news is that while you will have to use a user-agent workaround, you can use it for all iOS versions since they were already behaving like you weren’t autofocusing:

if (!/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
    element.focus();
}

This appears to be the approach http://www.google.com uses based on some basic user-agent testing:

  • Mac Book Pro: autofocus before page load.
  • iPhone: no autofocus
  • iPad: no autofocus
  • Kit Kat (Android): focus after page load, possibly doing extra detection for presence of software keyboard.

If you haven’t, you should go ahead and file a radar with Apple at https://bugreport.apple.com.

Leave a Comment