在Android网页中禁用输入焦点缩放


77

这是一个难题,我有一个网页(仅适用于android设备),并且在该页面中有一个输入框(特别是一个文本框),当焦点对准时,浏览器就会放大。我不希望它放大-声音容易吧?

这就是有趣的地方:我必须能够总体放大,所以不要说

<meta name='viewport' content='user-scalable=0'>

那对我不起作用。

此外,输入框不会收到点击事件。当单击另一个按钮以编程方式获得焦点时,将显示它。

这是我尝试过的,到目前为止,它们都失败了:

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" />');

这也失败了:

<input type='text' onfocus="return false">

还有这个:

jQuery("#locationLock input").focus(function(e){e.preventDefault();});

有任何想法吗?


因此,Chrome浏览器仅在输入字段中已有内容时才进行缩放,因此您可以尝试完美地删除内容,设置超时时间,然后稍后(大约150ms)重新添加内容。长期以来对输入字段的长期关注仍然存在一些问题。IMO,如果要执行此操作,请保持超时时间短,出于UX原因而添加一点jQuery加载效果,然后回退以仅将输入的字体大小设置为18px即可。那里的缩放功能使用户可以更轻松地更改插入符号的位置,因此也考虑一下。
niall.campbell 2014年

1
在此处为问题加注
Jo P

主持人注:随着时间的流逝,这个问题已经积累了30多个答案。在添加新答案之前,请确保尚未提供您的解决方案。
马特

Answers:


36

以下对我有用(Android Galaxy S2):

<meta name="viewport" content="width=device-width, height=device-height,  initial-scale=1.0, user-scalable=no;user-scalable=0;"/>

这绝对应该是当前正确的答案!
axelbrz 2015年

3
这可行。但是,您应该使用而不是; 我还猜想关于可用性的评论可能会被忽略,因为在某些情况下,由于我们明显想防止这种行为,因此在不良的可用性体验中,我们可能都在这里。
杰伊·德沃克(Jey DWork),2015年

可在iPhone X上使用。这应该是正确的答案
Shalin Nipuna

30

不可能!

我对你们所有人都有坏消息。现在已经6个月了,没有人正确回答这个问题。

另外,我已经完成了该项目和雇主的工作。

我怕这么说,但是我要的完全是不可能的。抱歉,人民。但是我将继续讨论这个问题,以便人们看到其他选择。


7
一年后有解决方案吗?
贾斯汀·云

12
好吧,现在呢?
Andrei Cristian Prodan 2014年

1
:添加星的铬问题的报告在这里得到这个由谷歌注意到code.google.com/p/chromium/issues/detail?id=181560
乔P

1
有很多解决方案,最好是确保您的文档正文不超过本机屏幕尺寸。
Tony Chiboucas

1
现在已正式发布:此烦人的功能现在终于在新版本的Chrome中删除!请参阅code.google.com/p/chromium/issues/detail?id=181560#c28codereview.chromium.org/196133011
Med

14

比例尺问题导致输入焦点放大

调整内容大小以适应不同的屏幕分辨率和尺寸非常困难,这最终是导致缩放问题的原因。

大多数移动浏览器都会触发输入焦点(您不能毫无困难地超越它):

if (zoom-level < 1)
   zoom to 1.5
   center focused input relative to screen

*是的,这过于简单了。

中继标记规模修正的神话。

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">如果缩小了 所有这些视口设置,将不会阻止输入焦点缩放。这些也不会覆盖任何其他html,body或element大小,它们会将窗口推到比屏幕更宽的宽度。

主要原因

使用大于设备屏幕尺寸的窗口或主体尺寸。

考虑大多数Android智能手机的Galaxy系列的标准屏幕尺寸:360 x650。如果文档主体或窗口的尺寸被定义为大于该尺寸(例如,要使其宽1024,则很明显),可能有几件事发生:

  1. 浏览器可能会自动缩小以适合屏幕宽度。
    1. 用户可以执行上述操作。
    2. 您可能已完成上述操作。
  2. 浏览器将在以后访问该页面时恢复缩放级别。
  3. 您现在正在以约0.35倍变焦查看内容。

初始状态1x

加载后,该页面将无法容纳。某些浏览器可能会缩小以适合窗口,但用户肯定会这么做。此外,如果您一次缩小了此页面,浏览器将存储缩放级别。

缩小以适合0.35倍

缩小后,宽度将非常合适,并且具有更大垂直区域的页面将很好地填充屏幕...但是...

请注意,浏览器现在处于这样的状态,即文本和输入(正常1倍缩放的大小)太小而无法阅读,因此触发输入字段获得焦点时缩放的可用性行为。

放大输入焦点1.5倍

在上述情况下,典型的行为是缩放至1.5倍,以确保输入可见性。结果(如果您将所有样式都设置为在缩小时或在较大的屏幕上看起来更好),则效果不理想。

解决方案1

结合使用CSS媒体规则,设备检测或最适合您的情况的设备。将窗口和主体的大小设置为可填充屏幕空间的大小,但不要超过该大小。

  • 这就是为什么如此多的人成功将输入文本大小强​​制为16px的原因。
    • 一旦执行此操作,就可以清楚地看到您已缩小。
    • 它还具有诱骗浏览器以允许稍微缩小窗口以不触发焦点缩放的附加好处。

解决方案2

使用元视口,但要注意CSS宽度。

<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
  • 使用此方法时,必须执行下列操作之一:
    • 仅对宽度使用百分比。
    • 定义em宽度,并且仅将em和%用于宽度。
    • 有关使用px宽度的信息,请参见解决方案1。

解决方案3

jQuery.mobile $.mobile.zoom.disable();

只要确保您从一开始就开始开发它,而不是从中间开始。


12

我不确定这是否是最好的方法,但这对我在android和iphone上有效。

input:focus { font-size: 16px!important}

您只能使用媒体查询来定位移动设备。


...此外,这通常是由于窗口/主体的尺寸/缩放不当引起的。
Tony Chiboucas

您不能使用媒体查询仅将移动设备的宽度或高度作为目标。许多触摸设备与台式设备一样大。触摸或非触摸设备检测是脚本还是服务器端。
克里斯蒂娜(Christina)2014年

我认为这甚至不是一个正确的答案。自动缩放的问题不仅在于“小字体”,而且还在于元素放置不正确的错觉。以我的情况为例,输入被放大并且不在屏幕上居中,因此当用户不知道此“自动缩放”时,我被报告为“错误的对话框位置”
Kamilius


4

今天就遇到这个问题,可能很快就会有铬的更新,可以解决这个问题。根据@Jo指出的问题,

no.28 jdd ... @ chromium.org自https://codereview.chromium.org/196133011/以来,在具有针对移动设备进行优化的视口(例如,“ width = device-width”或“固定”页面比例视口注释)。

将可编辑元素放在此类站点上时,可能仍会自动滚动,以保持元素的可见性,但是缩放将被禁用。这将在M41中上线(距离打通Beta频道还有很多星期)。

我们没有任何计划来防止传统桌面网站的自动缩放。

截至目前,Chrome浏览器版本为40;v.41在测试版中。将检查以确保焦点是否继续在Android Chrome浏览器上丢失。


修复了我的这种情况的实例。对我来说,此错误是在为媒体查询移动元素(包括带有两个文本输入的表单)时遇到的。使用jQuery的.insertBefore()/ .insertAfter()分解了某些内容,并使用.prependTo()/ .appendTo()起作用。也就是说,它并没有强迫Android Chrome重新调整输入焦点的大小。
cthorpe 2015年

3

我一直在研究这个问题,因为它对我的HTML5 Android应用程序一直很困扰。我可以提供一半的答案。也就是说,在聚焦文本字段时如何停止页面缩放。

需要Jquery Mobile:

$('#textfield').textinput({preventFocusZoom:true});

确实做到了。

但是,正如我所说,这只能解决一半的问题。另一半允许用户随后再次缩放页面。我发现的文档似乎表明

    $('#textfield').textinput({preventFocusZoom:false});

要么

$('#textfield').textinput('option','preventFocusZoom',false);

应该取消设置它,但是我没有设法使这两个选项起作用。如果您之后将用户带到另一个页面,这不是问题,但是如果像我一样,您只是要通过AJAX加载内容,则使用范围有限。

编辑:虽然针对IOS,

$.mobile.zoom.disable();

也停止缩放。以更适当的通用方式。但不幸的是

$.mobile.zoom.enable();

无法像以前的代码那样还原功能。


preventFocusZoom会对Android本机浏览器造成破坏。每次将表单输入聚焦时,页面都会滚动到顶部,输入将不会获得焦点,并且直到您再次尝试使输入聚焦时才会显示键盘。报告为错误。
比利

3
font-size: 18px;

这已针对运行Android 4.3的Nexus 7(2011)修复。

Nexus 7仅对我存在此问题,以下设备对字体大小都满意:16px:

  • HTC Desire Android 2.3.7
  • Nexus 4 Android 4.3

希望这对某人有帮助!


最近在Nexus4上进行了测试。发现18px不够。我使用点数,所以最终使用1.3em
wormhit 2014年

谢谢蠕虫。我发现我的Nexus 7最近不再出现缩放问题,这可能是Android 4.4导致的。
红苏

字体大小设置为18像素也确实起作用了Galaxy Note的3
列夫

强制将内容设置为特定的字体大小是不可接受的解决方案,因为HD分辨率屏幕上的16px或18px可读性差,除非您还使用css强制进行一定程度的缩放。这将使它成为非常糟糕的CSS
骇客

@TonyChiboucas但CSSpx不是设备的像素
z0r

2

这在哪里#inputbox是输入表单元素的ID。

我正在使用它来阻止搜索框自动缩放IOS,这是上面较早的帖子的修改版,因为mouseover事件只会在第一次运行,但无法触发后续时间。享受这是一个真正的拔毛器...

$("#inputbox").live('touchstart', function(e){
    $('head meta[name=viewport]').remove();
    $('head').prepend('<meta name="viewport" content="user-scalable=0" />');
    }
);

$("#inputbox").mousedown(zoomEnable);

function zoomEnable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="user-scalable=1" />');
}

2

附带说明:

meta name="viewport"完美的解决方案。但是,Android中的本机浏览器和Chrome浏览器都具有名为“覆盖网站控制缩放的请求”的可访问性设置如果设置了此设置,则HTML,CSS或JavaScript中的任何内容都不能禁用缩放。


2

您需要两件事:

在您的头上使用这样的元标记来避免用户缩放:

<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" />

然后在您的CSS中输入以下内容,以避免浏览器缩放:

* { font-size:16px; }

做完了!我认为浏览器会根据最小字体或类似字体来调整视口的大小。也许有人可以更好地解释它,但是它有效:)


为了测试,我在css * {font-size:16px!important; },变焦已完全消失。我认为页面中的一些文本太小会导致浏览器在聚焦输入时缩放。
Beto Aveiga

现在,我的页面在html结构中太复杂了。使用更简单的标记进行测试以找到更好的解决方案将是很好的。
Beto Aveiga

2

将此meta标签添加到您的html文件中,它将解决此问题。

<html><head><meta name='viewport' content='width=device-width, initial-scale=1.0, user-scalable=0' ></head><body>html code</body></html> 

1

工作模式

我们可以在Android上使用它。这里的关键是:在字体大小输入必须是适当的大小。如果您的页面宽度为320像素,则需要16像素的字体大小。如果您的大小是640像素,则需要32像素的字体大小。

另外,您需要以下内容

320宽版

<meta name="viewport" content="width=320, initial-scale=1, maximum-scale=1, minimum-scale=1" />

640宽版

<meta name="viewport" content="width=640, initial-scale=.5, maximum-scale=.5, minimum-scale=.5" />

注意:这不包含用户可缩放的属性。那会破坏它。


1

对于试图在隐藏的输入字段上聚焦时试图停止缩放的任何人,您都可以使隐藏的输入与屏幕区域(或可视区域)一样大(或至少与屏幕区域一样大)-这将停止缩放。

例如

HIDDENinput.style.width = window.innerWidth;

HIDDENinput.style.height = window.innerHeight; (可选的)


1

这可能是一个很好的答案:

input, textarea {
  max-width:100%;
}

不要使用 <meta name=viewport content='user-scalable=no'>


1

我不确定是否可以禁用缩放,但是可以设置类似的限制

 <meta id="viewport" name="viewport" content="width=device-width,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">

最大比例= 0.5最小比例= 0.5应该可以解决问题。它为我工作。


1

如果将输入的字体大小设置为16px,缩放将停止。移动浏览器假定小于16像素的内容表示用户需要缩放,所以我为什么不自己做。

 input[type='text'],input[type='number'],textarea {font-size:16px;}
 body{ -webkit-text-size-adjust:none;}

您也可以设置下面的meta标签,但是它会阻止用户完全扩展。

<meta name="viewport" content="width=device-width,  initial-scale=1.0, user-scalable=0;"/>

如果要用户缩放但仅禁用输入缩放,请尝试此操作

$("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" />');
}

也试试这个


1
@tobyodavies我的Android(HTC Desire S)实际上处理对viewportmeta标签的更改。我正在像这样重置缩放:$('meta[name=viewport]').attr('content', 'initial-scale=1.0, maximum-scale=0.05');但是这会导致浏览器将视口移到left,top = 0,0。
2012年

1

通常,您不想禁用辅助功能。

但是您可以通过简单地添加固定的div并将网页放在其中来解决缩放问题。

#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>

0

通过将缩放比例重置为1.0,也许可以避免缩放?在我的Android(HTC Wildfire S)上,我可以将缩放重置为1.0,如下所示:

$('meta[name=viewport]').attr('content',
         'initial-scale=1.0, maximum-scale=0.05');

但这会将视口移至0,0(页面的左上角)。于是我$().scrollLeft(...).scrollTop(...)回到form了。

initial-scale=1.0, maximum-scale=0.05是我的viewportmeta的初始值。)

(我这样做的原因不是防止Android缩放,而是将缩放重置为已知的比例,这是因为其他Android错误会损坏screen.width和其他相关值。)


0

试试这个,它可以在我的设备上运行:

<meta content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no" name="viewport" /> 

但是,当我双击输入框时,键盘会向上滑动,使页面的高度减小。


0

我偶然发现了:

 input {
     line-height:40px;
 }   

会阻止我的Galaxy Nexus和Android版本18上的Galaxy Nexus上的输入放大,尽管这可能与我的情况有关:

<meta name='viewport' data='width=800'>

因此,为将来参考,如果您通过Google来到这里,这可能是其他解决方案之一。


0

我遇到了同样的问题(仅在Android chrome浏览器中)。我解决了这样的问题。

  1. 检测到userAgent,并绑定文本字段的onFocus和onBlur事件以更改视口元内容,如下所示

    if ((navigator.userAgent.match(/Android/i)) && (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)) {
    isAndroidChrome = true;    
    }
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    
  2. 在文本字段的onFocus上,我设置了以下视口元内容 viewportmeta.content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1';

  3. 在文本字段的onBlur中,我正在将视口元内容重置为viewportmeta.content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.4'; 您可以根据需要设置最大比例,或者如果您希望它是用户可缩放的,则不要设置最大比例

当您更改触发器onFocus时,输入事件为maximum-scaleis 1,则不会放大。这对我来说就像一个魅力。希望它也对您有用。


0

正如@soshmo所说,user-scalable这不是WebKit喜欢的属性,因此包含它会导致WebKit丢弃整个视口标签。我还发现设置maximum-scale为1以外的任何其他情况并没有停止缩放。

重置viewportonfocusblurevent对我有用:

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");
    });
});

如果发现该设置/重置,viewport则值得检查WebKit是否接受您正在使用的内容属性。我花了一段时间才意识到,使用之类的东西会user-scalable导致viewport废弃,因此即使JavaScript工作正常,更改也不会受到影响。


0

在touchstart上设置视口用户可缩放属性对我来说是成功的,无需删除然后重新添加,只需在touchstart上对其进行更改,然后在模糊时再次启用即可。意味着用户在专注于该领域时无法变焦,但我认为付出的代价很小。

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);

0

对于Nexus 7,我的媒体查询是-

@media screen and (max-device-width: 600px) and (orientation : portrait)

所以我用下面的媒体查询来解决这个问题-

@media screen and (max-device-width: 600px) and (max-aspect-ratio: 13/9)


0

参加聚会有点晚,但是昨天我花了整整一个下午疯了,然后才到达这篇文章,意识到这是Android的功能/错误。因此,我将发布解决方案。这对我有用,仍然可以使用户缩放:

元:

<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;
}

将HTML设置为position:absoluteoverflow-x:hidden帮了我大忙。


0

适用于星系4:
将代码添加到HTML标头索引文件:

<meta name="viewport" content="width=device-width, height=device-height,  initial-scale=1.0, user-scalable=no;user-scalable=0;"/>


0

我发布了答案,因为我遇到了类似的问题并解决了。

我的情况如下。

html head中的视口设置为

<meta name="viewport" content="width=640">

代理是Android默认浏览器。
它们不是Chrome,Firefox和Safari。
Android版本低于4.2.x。

我们所处情况的细节并不相同,但我认为它们有一个本质上相同的问题。

我解决了将“ target-densitydpi = device-dpi”添加到meta [name = viewport]标签的问题。

<meta name="viewport" content="width=640, target-densitydpi=device-dpi">

请尝试一下。

但是我不得不说“ target-densitydpi = device-dpi”会产生副作用。

坏情况在这里。

  1. 安卓OLD浏览器读取“ target-densitydpi = device-dpi”。
  2. 它将转到没有target-densitydpi属性的另一页。
  3. 浏览器开始将页面呈现为“ target-densitydpi = device-dpi”。
  4. 因此,它将以错误的比例因子呈现下一页。

这种情况的解决方案是在转到下一页之前,使用javascript将target-densitydpi属性从“ device-dpi”重写为“ medium-dpi”。

使用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>

而且...此代码导致了新问题。
某些浏览器使用后退按钮返回上一页时,会使用缓存数据来呈现javascript处理的结果。因此,他们将前一页显示为“ target-densitydpi = medium-dpi”,而不显示为“ target-densitydpi = device-dpi”。

一个解决方案与上述相反。

<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>

谢谢。


0

保持内容比窗口窄。

考虑到这一点,您必须从一开始就设计页面,但这是完全有效的。

关键是要使用@mediaCSS规则仅允许组件具有您知道屏幕足以容纳的宽度。

例如,如果您设置了内容宽度,以使文本不会在较大的显示器上散布开,请确保该宽度仅适用于大屏幕:

@media (min-width: 960px){
.content{
  width : 960px;
}
}

或者,也许您有一个500像素宽的图像,则可能必须将其隐藏在较小的屏幕上:

@media (max-width: 500px){
.image{
  display : none; 
}
}

0

尝试使用它,这将适合设备的大小,并避免放大/缩小

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.