Reputation: 4868
Here's the dilema, I have a webpage (only for android devices) and in that page I have an input box (a text box specifically) and when it gets focus the browser zooms in. I don't want it to zoom in - sounds easy, right?
Here's where it gets fun: I have to be able to zoom in general so don't say
<meta name='viewport' content='user-scalable=0'>
That won't work for me.
Also, the input box doesn't receive click events. It appears when another button is clicked a gets focus programmatically.
Here's what I've tried and they've failed so far:
jQuery('head meta[name=viewport]').remove();
jQuery('head').prepend('<meta name="viewport" content="width=720px;intial-scale=1.0;maximum-scale=1.0;user-scalable=no" />');
jQuery("#locationLock input").focus();
jQuery('head meta[name=viewport]').remove();
jQuery('head').prepend('<meta name="viewport" content="width=720px;intial-scale=1.0;maximum-scale=1.0;user-scalable=yes" />');
This also failed:
<input type='text' onfocus="return false">
And this:
jQuery("#locationLock input").focus(function(e){e.preventDefault();});
Any ideas?
Upvotes: 98
Views: 110872
Reputation: 71
I've had a similar issue, you need to ensure that the font size of your input field is at least 16px.
Upvotes: 1
Reputation: 1
Use JavaScript to handle zoom behavior If the above methods don't completely solve the issue, you can use JavaScript to programmatically control zoom behavior. This method might be more complex and less performant, so it should be used as a last resort.
document.addEventListener('touchstart', function(event) {
if (event.touches.length > 1) {
event.preventDefault();
}
}, { passive: false });
let lastTouchEnd = 0;
document.addEventListener('touchend', function(event) {
let now = (new Date()).getTime();
if (now - lastTouchEnd <= 300) {
event.preventDefault();
}
lastTouchEnd = now;
}, false);
Upvotes: 0
Reputation: 109
There is a CSS solution:
input{ touch-action: none; }
Upvotes: 10
Reputation: 78
You can add appearance:none
into the css of the input element:
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
Upvotes: 0
Reputation: 19
Update 2021
Coming back in 2021 to update my answer -> from a few accessibility conversations with my colleagues. This issues is caused by an accessibility feature for inputs with font-sizes smaller than 16px. Which means you should solve this issue by using a font size greater than or equal to 16px (1rem). This means you should solve it at your design level (designers not sucking at accessibility) rather than limiting an accessibility feature like I have above.
Original
Typically you don't want to disable the accessibility features.
But you can get around the zoom issue by simply adding a fixed div and placing your web page inside it.
#app {
position: fixed;
top: 0em;
bottom: 0em;
left: 0em;
right: 0em;
overflow: scroll;
}
<body>
<div class="app">
<!-- the rest of your web page -->
<input type="text">
</div>
</body>
<body>
<div class="app">
</div>
</body>
Upvotes: 1
Reputation: 1
From what I tried the best thing that worked is to make the font inside the input 16px or more. Definitely works on the last version on chrome.
Upvotes: -1
Reputation: 49
Try using this, this will fit into device size and avoid zoom in/out
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
Upvotes: -2
Reputation: 219
add this meta tag to your html file and it will solve the issue.
<html><head><meta name='viewport' content='width=device-width, initial-scale=1.0, user-scalable=0' ></head><body>html code</body></html>
Upvotes: 1
Reputation: 1182
You will have to design your page from the beginning with this in mind, but it is entirely effective.
The key is to use the @media
css at-rule to only allow components to have widths that you know the screen is big enough to contain.
For example, if you have a content width set so that the text doesn't get too spread out on a larger monitor, make sure that width only applies to large screens:
@media (min-width: 960px){
.content{
width : 960px;
}
}
Or maybe you have an image that is 500px wide, you might have to hide it on smaller screens:
@media (max-width: 500px){
.image{
display : none;
}
}
Upvotes: 0
Reputation: 478
This may be a solution to that kind of probleme
<meta name="viewport" content="user-scale=no"/>
<meta name="viewport" content="width=device-width"/>
<meta name="viewport" content="width=device-width, maximum-scale=0.9"/>
Upvotes: -2
Reputation: 5683
There is a great difficulty in sizing the content for different screen resolutions and sizes, which ultimately is the cause of this zoom issue.
Most mobile browsers have a trigger on input focus (that you can't over-ride without difficulty):
if (zoom-level < 1)
zoom to 1.5
center focused input relative to screen
*yes, that was way over-simplified.
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
All such viewport settings will not prevent the input-focus zoom if you are zoomed-out.
These will also not over-ride any other html, body, or element sizing that would push the window to width wider than the screen.
Using a window or body size larger than the device screen dimensions.
Consider the standard screen-size of most of the Galaxy line of Android smartphones: 360 x 650. If your document body, or window, is defined to be larger than that (let's say 1024 wide to make it obvious), a few things may happen:
When loaded, the page won't fit. Some browsers may zoom-out to fit the window, but the user most certainly will. Additionally, if you zoomed-out on this page once, the browser will store the zoom-level.
Once zoomed out, the width will fit nicely, and a page with more vertical area will fill out the screen quite nicely... but...
Notice that the browser is now in a state where text and input (sized for normal 1x zoom) would be way too small to read, thus triggers a usability behavior of zooming on the input fields when they get focus.
Typical behavior in the above case, is to zoom to 1.5x, to ensure input visibility. The result (if you've styled everything to look better when zoomed-out, or for the larger screen) is less than desirable.
Use a combination of css media rules, device-detection, or whatever best suits your situation. Set the window and body to a size that fills the screen-space, without exceeding it.
Use the meta viewport, but then be careful with css widths.
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
jQuery.mobile $.mobile.zoom.disable();
Just make sure you start developing with it from the start, and not from the middle.
Upvotes: 20
Reputation: 1
I post a answer because I faced a similar problem and I resolved it.
My condition is below.
A viewport setting in html head is
<meta name="viewport" content="width=640">
Agents are Android default browser.
They aren't Chrome, Firefox and Safari.
Android versions are under 4.2.x.
Details of our situations are not same but I think they have an essentially equal problem.
I resolved it to add "target-densitydpi=device-dpi" into meta[name=viewport] tag.
<meta name="viewport" content="width=640, target-densitydpi=device-dpi">
Try it please.
But I have to say that "target-densitydpi=device-dpi" would have a side effect.
Bad case is here.
A solution of this case is to rewrite target-densitydpi property to "medium-dpi" from "device-dpi" using javascript before going to the next page.
An example using jQuery.
<a href="go-to-the-other" class="resetDensityDpi">Other page</a>
<script>
$(function(){
$('.resetDensityDpi').click(function(){
var $meta = $('meta[name="viewport"]');
$meta.attr('content', $meta.attr('content').replace(/target-densitydpi=device-dpi/, 'target-densitydpi=medium-dpi'));
return true;
});
});
</script>
And... this code causes a new problem.
Some browsers render results of javascript process using cache data when they go back to previous page using a back button.
So they display the previous page as "target-densitydpi=medium-dpi" NOT as "target-densitydpi=device-dpi".
A solution of this is just the opposite of above.
<script>
$(function(){
var rollbackDensityDpi = function() {
// disable back-forword-cache (bfcache)
window.onunload = function(){};
var $meta = $('meta[name="viewport"]');
if ($meta.attr('content').match(/target-densitydpi=medium-dpi/)) {
$meta.attr('content', $meta.attr('content').replace(/target-densitydpi=medium-dpi/, 'target-densitydpi=device-dpi'));
}
};
if (window.addEventListener) {
window.addEventListener("load", rollbackDensityDpi, false);
} else if (window.attachEvent) {
window.attachEvent("onload", rollbackDensityDpi);
} else {
window.onload = rollbackDensityDpi;
}
});
</script>
Thank you.
Upvotes: 0
Reputation: 38352
If you set font size of input to 16px the zoom stops. Mobile browsers assume anything less than 16px means the users will need to zoom so why don't i do it myself.
input[type='text'],input[type='number'],textarea {font-size:16px;}
body{ -webkit-text-size-adjust:none;}
You may also set the below meta tag but it prevent user scaling completely.
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0;"/>
If you want user scaling but only disable input scaling try this
$("input[type=text], textarea").mouseover(zoomDisable).mousedown(zoomEnable);
function zoomDisable(){
$('head meta[name=viewport]').remove();
$('head').prepend('<meta name="viewport" content="user-scalable=0" />');
}
function zoomEnable(){
$('head meta[name=viewport]').remove();
$('head').prepend('<meta name="viewport" content="user-scalable=1" />');
}
also try this
Upvotes: 4
Reputation: 99
I'm not sure if you can disable the zoom, but you can set a restriction like this
<meta id="viewport" name="viewport" content="width=device-width,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">
maximum-scale=0.5 and minimum-scale=0.5 should do the trick. It worked for me.
Upvotes: 1
Reputation: 420
This may be good answer:
input, textarea {
max-width:100%;
}
Don't use <meta name=viewport content='user-scalable=no'>
Upvotes: 1
Reputation: 214
For anyone that is trying to stop zoom when trying to focus on a hidden input field, you can make the hidden input as big (or at least as wide) as the screen area(or viewable area) - this stopped it zooming.
e.g.
HIDDENinput.style.width = window.innerWidth;
HIDDENinput.style.height = window.innerHeight;
(optional)
Upvotes: 1
Reputation: 31
Worked for galaxy 4 :
Add the code to HTML header index file :
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no;user-scalable=0;"/>
Upvotes: 0
Reputation: 4157
Bit late to the party, but I spent a whole afternoon yesterday going nuts before I got to this post and realized it was a feature/bug from Android. So I'll post my solution. This worked for me, and still enables user zoom:
Meta:
<meta id="meta1" name="viewport" content="width=device-width,initial-scale=1,minimal-ui"/>
CSS:
html{
position:absolute;
overflow:-moz-scrollbars-vertical;
overflow-y:scroll;
overflow-x:hidden;
margin:0;padding:0;border:0;
width:100%;
height:100%;
}
body{
position: relative;
width: 100%;
height: 100%;
min-height:100%;
margin: 0;
padding: 0;
border: 0;
}
Setting HTML to position:absolute
and overflow-x:hidden
did the trick for me.
Upvotes: 0
Reputation: 3670
You need 2 things:
Use a metatag like this in your head to avoid the user from zooming:
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
And then in your css put something like the following to avoid the browser from zooming:
* { font-size:16px; }
Done! I think the browser resizes your viewport based on the smallest font or something like that. Maybe someone could explain it better, but it worked :)
Upvotes: 3
Reputation: 133
Ran into this issue today and may have a chromium update coming down the pipe soon that could resolve it. Per the chromium issue pointed to by @Jo,
no.28 [email protected] As of https://codereview.chromium.org/196133011/, autozooming is disabled on sites that have a mobile-optimized viewport (e.g., "width=device-width" or fixed page scale viewport annotation).
There may still be auto-scrolling when focusing editable elements on such sites, to maintain the element's visibility, but zooming will be disabled. This will go live in M41 (still a good number of weeks from hitting beta channel).
We don't have any plans to otherwise prevent autozooming for legacy desktop sites.
As of this time, Chrome is v.40; v.41 is in BETA. Will be checking in to see if focus continues to be lost on the Android Chrome browser.
Upvotes: 4
Reputation: 651
Just a side note:
The solution with the meta name="viewport"
works perfectly. However, both native and Chrome browsers in Android have an accessibility setting named "Override website's request to control zoom". If this setting is set, nothing in HTML, CSS, or JavaScript can disable zooming.
Upvotes: 2
Reputation: 1
add this meta tag to your html file and it will solve the issue.
<meta name="viewport" content="width=device-width, user-scalable=no" />
adding this line solved issue for me in HTC desire 816 and SAMSUNG GALAXY S5.
Upvotes: -1
Reputation: 1
For Nexus 7 I was getting this issue when my media query was -
@media screen and (max-device-width: 600px) and (orientation : portrait)
So I used below media query to resolve the issue -
@media screen and (max-device-width: 600px) and (max-aspect-ratio: 13/9)
Upvotes: 0
Reputation: 1
SOLUTION FOUND!!!!!!!!!!!!!!!
At least for people that works with Phonegap/Cordova
I'm using a Galaxy Tab pc1010 with Android Froyo (2.2) I'm using Cordova 2.4.0
Add these beautiful lines to your HTML head element:
<meta name="viewport" content="user-scale=no"/>
<meta name="viewport" content="width=device-width"/>
<meta name="viewport" content="width=device-width, maximum-scale=0.9"/>
Type them separately and use maximum scale of 0.9. I was having this problem when selecting an input field that my layout disadjusted just a little bit from the top and from the left, tried to repair it using javascript element style modification but it was awful. Thank God I found this configuration in an old mobile site project created using some tutorials with this trick.
Upvotes: -3
Reputation: 1049
This works great for me.
input[type='text'],input[type='number'],textarea {font-size:16px; !important}
Upvotes: -3
Reputation: 11
Setting the viewport user-scalable property on touchstart did it for me, no need to remove then re-add simply change it on touchstart then enable again on blur. Means the user can't zoom whilst focused on the field but a small price to pay I think.
var zoomEnable;
zoomEnable = function() {
$("head meta[name=viewport]").prop("content", "width=device-width, initial-scale=1.0, user-scalable=yes");
};
$("input[type='text']").on("touchstart", function(e) {
$("head meta[name=viewport]").prop("content", "width=device-width, initial-scale=1.0, user-scalable=no");
});
$("input[type='text']").blur(zoomEnable);
Upvotes: 0
Reputation: 25
As @soshmo said, user-scalable
isn't an attribute that WebKit likes and so its inclusion causes WebKit to discard the whole viewport tag. I also found this to be the case with setting maximum-scale
to anything other than 1, and that didn't stop the zooming.
Resetting the viewport
on every focus
and blur
event worked for me:
var htmlWidth = parseInt($('html').outerWidth());
var screenDPI = parseInt(window.devicePixelRatio);
var screenWidth = parseInt(screen.width);
var screenHeight = parseInt(screen.height);
var scaleVal = (((screenWidth * screenDPI) / htmlWidth)/screenDPI);
$('input[type="text"], input[type="password"], input[type="email"]').each(function() {
//unchained for clarity
$(this).focus(function() {
$('meta[name="viewport"]').attr('content', "initial-scale=' + scaleVal + ', maximum-scale=1, minimum-scale=' + (scaleVal) + ', width=device-width, height=device-height");
// Do something to manage scrolling the view (resetting the viewport also resets the scroll)
$('html, body').scrollTop(($(this).offset().top - (screenHeight/3)));
});
$(this).blur(function() {
$('meta[name="viewport"]').attr('content', "initial-scale=' + scaleVal + ', maximum-scale=1, minimum-scale=' + (scaleVal) + ', width=device-width, height=device-height");
});
});
If you find that setting/resetting the viewport
it's worth checking that WebKit accepts the content attributes that you're using. It took me a while to realise that using things like user-scalable
caused the viewport
to be discarded, so even though the JavaScript was working, the changes were not affected.
Upvotes: 0
Reputation: 49
font-size: 18px;
This fixed it for my Nexus 7 (2011) running Android 4.3.
This problem only exists for me on the Nexus 7, the following devices all appear happy with font-size: 16px:
Hope this helps someone!
Upvotes: 4
Reputation: 308
Working Model
We have this working on Android. Here is the key: the font-size on the input must be the proper size. If you're page is 320px wide then you need 16px font size. If you're size is 640px then you need 32px font size.
In addition you need the following
320 wide version
<meta name="viewport" content="width=320, initial-scale=1, maximum-scale=1, minimum-scale=1" />
640 wide version
<meta name="viewport" content="width=640, initial-scale=.5, maximum-scale=.5, minimum-scale=.5" />
NOTE: THIS DOES NOT CONTAIN THE USER SCALABLE ATTRIBUTE. THAT WILL BREAK IT.
Upvotes: 1
Reputation: 1128
I'm not sure if this is the best way but this works for me on android and iphone.
input:focus { font-size: 16px!important}
You can use media queries to target mobile devices only.
Upvotes: 13