the problem
Imagine the following scenario: you are in the final stages of developing a shiny, new, state of the art responsive website. Everything looks beautiful on your desktop machine; when you resize every breakpoint kicks in as planned and the site adapts elegantly. Before you kick back and declare the project complete you need to give the site a final shakedown on a couple of real world mobile devices.
Page after page everything looks pixel perfect … until you come to the contact form. Imagine your horror as you click into the first textbox and the whole screen zooms in so pretty much the only thing visible is one giant input field! Sadly this nightmare scenario is a reality on many devices, especially those made by Apple Inc.
Googling for a solution to this annoying issue often yields the suggestion of setting the font-size on the input to 16px. Whilst this does solve the problem on many devices it still spoils your carefully crafted design. If you’ve set the input to be font-size: 12px then that’s how you want it to display!
The other popular solution is to disable zooming on the page entirely by setting user-scalable=0 within the viewport meta tag. This idea works well in practise, however it’s not very user friendly – some users may want (or need) to zoom into parts of your page.
If we could evolve this second idea to disable zooming temporarily – specifically, long enough for the device to believe it’s not allowed to interfere with the zoom level – then we may be onto something …
the solution
As mentioned above, the key here is to trick the device into thinking it’s not allowed to zoom when a user clicks a form field. The simplest way to do this is with javascript (note that we're running jQuery here as well):
var $objHead = $( 'head' );
// define a function to disable zooming
var zoomDisable = function() {
$objHead.find( 'meta[name=viewport]' ).remove();
$objHead.prepend( '<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=0" />' );
};
// ... and another to re-enable it
var zoomEnable = function() {
$objHead.find( 'meta[name=viewport]' ).remove();
$objHead.prepend( '<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=1" />');
};
// if the device is an iProduct, apply the fix whenever the users touches an input
if( navigator.userAgent.length && /iPhone|iPad|iPod/i.test( navigator.userAgent ) ) {
// define as many target fields as your like
$( ".search-form input, .contact-form input" )
.on( { 'touchstart' : function() { zoomDisable() } } )
.on( { 'touchend' : function() { setTimeout( zoomEnable , 500 ) } } );
}
There’s no real magic in this solution – all we need to do is wait for a user touch event and, at that point, update the page meta tag so that zooming is disabled. When the touch action ends we simply re-enable the zoom behaviour after a short delay. Our page design will remain unchanged and the user will be unaware that anything out of the ordinary has occurred!