This article was written in 2011. It might or it might not be outdated. And it could be that the layout breaks. If that’s the case please let me know.

Prevent iOs from zooming onfocus

UPDATE: The easiest (and the best) way to prevent iOs from zooming when a text field receives focus is by setting the font-size to 16px. (or better, by using the browser’s default font-size). A much harder solution is explained below. I don’t recommend it, just use the default font-size instead.

WARNING: This technique causes some serious issues on some Andriod devices. On some devices the keyboard is never shown, on others the keyboard is shown when you tap the field again. Until there’s a proper solution I would advice not to use this script.

When a form element gets focus on iOs the browser zooms in on that element. Very handy in unoptimized layouts where that element might be a few pixels high but annoying and unnecessary in a mobile optimized layout. You can disable this behaviour by changing the meta viewport value onfocus and onblur.
Here’s a simple jQuery example:

$('input, select, textarea').focus(function(){
$('meta[name=viewport]').attr('content','width=device-width,initial-scale=1,maximum-scale=1.0');
});
$('input, select, textarea').blur(function(){
$('meta[name=viewport]').attr('content','width=device-width,initial-scale=1,maximum-scale=10');
});

Notice the tiny difference between focus and blur: onfocus you set the maximum-scale to 1 and onblur it’s set to 10. You shouldn’t use the code above, Wilfred Nas and Mathias Bynens optimized it in the comments to this snippet:

var $viewportMeta = $('meta[name="viewport"]');
$('input, select, textarea').bind('focus blur', function(event) {
$viewportMeta.attr('content', 'width=device-width,initial-scale=1,maximum-scale=' + (event.type == 'blur' ? 10 : 1));
});

The browser starts zooming in but immediately zooms out again when the elements gets focus. I like that.

Comments

  1. Vasilis, ain’t this an idea. just to avoid code duplication:

    $(‘input, select, textarea’).bind(‘focus blur’,function(){
    $(‘meta[name=viewport]’).attr(‘content’,’width=device-width,initial-scale=1,maximum-scale=1.0′);
    });

    (just my 2cents)

    • Vasilis
    • #

    @wilfred: I’m sure the code can be refined but the content-attribute is not the same onfocus and onblur so I think your code won’t work.

  2. var $viewportMeta = $('meta[name="viewport"]');
    $('input, select, textarea').bind('focus blur', function(event) {
    $viewportMeta.attr('content', 'width=device-width,initial-scale=1,maximum-scale=' + (event.type == 'blur' ? 10 : 1));
    });

    • Vasilis
    • #

    Haha, I was waiting for that comment. Thanks Mathias! I updated the post.

    • Dave
    • #

    Pfft @mathias. Why the sudden urge to be readable? :-P

    $(‘input, select, textarea’).bind(‘focus blur’, function(e) { $(‘meta[name=”viewport”]’).attr(‘content’, ‘width=device-width,initial-scale=1,maximum-scale=’ + (e.type == ‘blur’ ? 10 : 1));});

  3. Dave: Your script would re-query the DOM to look for the viewport meta element every time a form element is focused or blurred. That’s why I use $viewportMeta as a cache.

    Other than that, the only change I see is that you renamed event into e. In case you’re wondering why I didn’t do that: I believe that’s what minifiers are for :)

    Is there anything else I’m missing?

    • dungnp
    • #

    I did this like as you but code won’t work. Do not prevent iOs from zooming onfocus. Please help me. Thanks.