标记的 HTML 页面。当我在 iPhone 上使用 Safari 单击它时,页面会变大(自动缩放)。有人知道如何禁用它吗?" /> 标记的 HTML 页面。当我在 iPhone 上使用 Safari 单击它时,页面会变大(自动缩放)。有人知道如何禁用它吗?"> 标记的 HTML 页面。当我在 iPhone 上使用 Safari 单击它时,页面会变大(自动缩放)。有人知道如何禁用它吗?" />
ChatGPT解决这个技术问题 Extra ChatGPT

禁用自动放大输入“文本”标签 - iPhone 上的 Safari

我制作了一个带有 type="text"<input> 标记的 HTML 页面。当我在 iPhone 上使用 Safari 单击它时,页面会变大(自动缩放)。有人知道如何禁用它吗?

对于所有登陆此处的 Twitter Bootstrap 用户:另请参阅this Github issue
我认为@daxmacrog 的答案完全符合您的要求,您是否愿意接受它,以便它可以上升到顶部并节省阅读所有这些内容的人们的大量返工? 2018 年答案:stackoverflow.com/a/46254706/172651
我发誓,Apple 创建这些反功能只是为了弄乱我们的头脑。
@AndrewKoster,即使在 2020 年,我也同意你的看法。
2020 年 8 月,又一次,我回到了这里,希望答案中出现奇迹。明年见。我要吃一个苹果。

d
daxmacrog

您可以防止 Safari 在用户输入期间自动放大文本字段而不禁用用户捏缩放的能力。只需添加 maximum-scale=1 但忽略其他答案中建议的 user-scale 属性。

如果您的图层中有一个表单在缩放时会“浮动”,这是一个值得选择的选择,这可能会导致重要的 UI 元素移出屏幕。

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">


这是 2018+ 解决方案。像你的生活依赖它一样投票。
这将破坏 android 设备的缩放能力
@HenrikPetterson这不仅仅是禁用OP指定的自动缩放,它还禁用捏缩放。所以我不认为这是 2018+ 的解决方案。
@AndréWerlang 这不准确。正如答案中明确指出的那样,此解决方案不会禁用 Safari(或 Firefox)中的捏缩放,这是 OP 所要求的。但正如之前的评论中所指出的,它确实禁用了 Android 设备和 iOS 上的 Chrome 上的用户缩放。
关于 maximum-scale=1 是否会令人讨厌地禁用用户捏缩放,有很多困惑。当 Apple 正确地决定忽略禁用用户捏缩放时,这种行为在 iOS 10 中发生了变化。好消息是该设置仍然可以防止自动变焦对焦。
I
Ivar

如果字体大小小于 16px 并且表单元素的默认字体大小为 11px(至少在 Chrome 和 Safari 中),浏览器将缩放。

此外,select 元素需要附加 focus 伪类。

input[type="color"],
input[type="date"],
input[type="datetime"],
input[type="datetime-local"],
input[type="email"],
input[type="month"],
input[type="number"],
input[type="password"],
input[type="search"],
input[type="tel"],
input[type="text"],
input[type="time"],
input[type="url"],
input[type="week"],
select:focus,
textarea {
  font-size: 16px;
}

没有必要使用以上所有内容,您可以只设置您需要的元素的样式,例如:只需 textnumbertextarea

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

让输入元素从父样式继承的替代解决方案:

body {
  font-size: 16px;
}
input[type="text"] {
  font-size: inherit;
}

只是为了涵盖所有内容:select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"] { font-size: 16px; }
@Nic 您需要使用 select:focus。也有同样的问题。
没看懂,怎么解决?如果我想要更小/更大的字体怎么办?
正确的方法是将元标记更改为:
@MilosMatic 在大多数情况下可能不是一个好的解决方案,因为它完全阻止用户缩放页面。对您的访问者来说可能更烦人。
C
Christina
@media screen and (-webkit-min-device-pixel-ratio:0) { 
  select:focus,
  textarea:focus,
  input:focus {
    font-size: 16px;
    background: #eee;
  }
}

新:IOS 仍然会缩放,除非您在没有焦点的输入上使用 16px。

@media screen and (-webkit-min-device-pixel-ratio:0) { 
  select,
  textarea,
  input {
    font-size: 16px;
  }
}

我添加了背景,因为 IOS 在选择时没有添加背景。


这不仅适用于 iOS(iphone/ipad/ipod)上的 safari,也适用于 Safari/OSX 和 Chrome(windows 和 Mac)。因此,如果您尝试专门针对 iphone,这将不起作用。
为什么每个人都说 16px,但没人关心为什么是 16px?为什么这么随意的数字?为什么我们必须将表单字段的文本大小设置为 16px 而不是 .. 说 1.8rem 或 2.5em 之类的?这只是专有操作系统的愚蠢错误吗?
@Beebee 100% 字体大小是 16px,这是大多数浏览器(如果不是所有浏览器)(桌面也是)的默认值。 IOS 使用它作为默认值可能是因为它的大小适合阅读。为什么这样设置我懒得抬头看,不在乎。
使用 @media screen and (-webkit-min-device-pixel-ratio:0) and (max-device-width:1024px) 将效果限制在 iPhone 上,但在 Chrome 中查看时不要修改网站。
不应使用媒体查询,而应使用 @supports (-webkit-overflow-scrolling: touch),因为此 css 功能仅存在于 iOS
a
alex

如果您的网站是为移动设备正确设计的,您可以决定不允许扩展。

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

这解决了您的移动页面或表单将“浮动”的问题。


技术上是正确的,但我不同意这个推理。在设计合理的网站上禁用用户缩放通常仍然是个坏主意。
“设计得当”是非常主观的。考虑一个固定的、50px 的标题在一个完全响应的站点顶部并且应该在所有浏览器中工作。放大 iOS Safari 会破坏标题定位,并且几乎会破坏整个网站。
从用户体验的角度来看,禁用用户缩放功能是一种糟糕的做法,应该不惜一切代价避免。能够自由放大是一项基本的辅助功能,并且是您永远不应该从用户手中夺走的控件。
在原生移动应用程序中,您永远没有机会缩放,而且它们工作得很好,为什么 web 应用程序会有所不同?如果您设置适当的字体大小和行高并具有明显的对比,您应该没问题。
那些使用“在本机应用程序中很好”论点的人忽略了一个事实,即制作精良的本机应用程序遵循操作系统级别的可访问性设置,例如文本大小。因为他们需要,年长和视力不好的用户可以并且确实使用非常大的操作系统范围的字体大小。 Web 应用程序通常不会或不能遵守此设置,因此允许 Web 浏览器的内置辅助功能(例如缩放)至关重要。无论您认为什么都可读,相信我,有些人会觉得它不够清楚。如果您重视可用性,请不要将此选项从用户手中夺走。
M
Mladen Janjetovic

总而言之,答案是:将表单元素的字体大小设置为至少 16px


是的,这绝对是避免在移动设备上缩放的最佳做法。没有 js,没有 hack,根本没有变通方法。但即使是 16 像素,我也注意到我的页面放大很小,所以我尝试了 17 像素、18 像素……看看会发生什么。
最佳实践是在 body、button、input、textarea 和 select 元素上声明 100%。这允许用户设置不是浏览器附带的 16px 的默认值。在屏幕上阅读有困难的人可能会将其默认设置为 18 像素或 20 像素。您不想通过在他们身上强制 16px 来覆盖他们的选择。然而,当谈到 iOS 时,他们决定扩大他们的 HIG 所说的任何价值太小。不幸的是,它看起来并没有解释 100% 的值,所以我们只能添加默认值来安抚它。
RE iOS Safari,截至此评论,Safari 似乎正确解释了 font-size: 100% 值并获取了必要的 16px。
f
fabb

解决此问题的正确方法是将元视口更改为:

重要提示:不要设置 minimum-scale!这使页面可以手动缩放。


这不一定是防止这种行为的“正确”方式。如果文本太小而无法阅读,Mobile Safari 会放大。关闭所有缩放功能很繁琐,并且会阻止用户以他们可能期望的方式与您的页面进行交互。
显然,在 iOS10 中,Apple 将 maximum-scale 属性更改为不再受到尊重,允许所有站点放大而不管其设置如何。
这适用于 iOS10 20/September/2016 版本...至少适用于我的应用程序...谢谢!!!在我使用 但我将其切换到响应行并有效...
“确保浏览器缩放缩放不会被页面的视口元元素阻止,以便可以将页面缩放到 200%。应避免此元元素的用户可缩放和最大缩放属性的限制值。” w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
这在 ios 中有效,但在 android 中,pich 缩放不起作用
s
stamat

正如许多其他答案已经指出的那样,这可以通过将 maximum-scale 添加到元 viewport 标记来实现。但是,this has the negative consequence of disabling user zoom on Android devices。 (It does not disable user zoom on iOS devices since v10。)

当设备为 iOS 时,我们可以使用 JavaScript 将 maximum-scale 动态添加到元 viewport。这实现了两全其美:我们允许用户缩放阻止 iOS 放大焦点上的文本字段。

| maximum-scale             | iOS: can zoom | iOS: no text field zoom | Android: can zoom |
| ------------------------- | ------------- | ----------------------- | ----------------- |
| yes                       | yes           | yes                     | no                |
| no                        | yes           | no                      | yes               |
| yes on iOS, no on Android | yes           | yes                     | yes               |

代码:

const addMaximumScaleToMetaViewport = () => {
  const el = document.querySelector('meta[name=viewport]');

  if (el !== null) {
    let content = el.getAttribute('content');
    let re = /maximum\-scale=[0-9\.]+/g;

    if (re.test(content)) {
        content = content.replace(re, 'maximum-scale=1.0');
    } else {
        content = [content, 'maximum-scale=1.0'].join(', ')
    }

    el.setAttribute('content', content);
  }
};

const disableIosTextFieldZoom = addMaximumScaleToMetaViewport;

// https://stackoverflow.com/questions/9038625/detect-if-device-is-ios/9039885#9039885
const checkIsIOS = () =>
  /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

if (checkIsIOS()) {
  disableIosTextFieldZoom();
}

为什么要创建 addMaximumScaleToMetaViewport 的副本?仅仅是出于语义原因吗?
是的,只需将函数映射到不同的名称,以便清楚它是如何使用的。
2021 年截至目前的最佳解决方案(带有一些排列的代码)
s
stormsweeper
input[type='text'],textarea {font-size:1em;}

请注意,将 user-scalable 设置为 no 将禁用所有缩放,这可能是个坏主意。
这仅在您的正文字体大小为默认值(未指定,或 1em,或 100%)时才有效。如果您设置自定义字体大小,您可以将代码段中的 font-size 设置为 16px 以避免自动缩放。
我知道这个问题是针对 iPhone 的,但这在跨平台和更多平台/设备的未来更兼容,我尝试了 16px 方法,但在 Android 平板电脑上只会降低自动缩放效果。按照帖子中的说明设置为“1em”解决了这个问题。
我有一个自定义字体大小(15px),并将字体大小设置为 1rem(不是 em)有效。
1em1rem 都不是合适的解决方案,因为两者都可能小于 16px,而且 Safari 至少需要 16px 才能不缩放。
C
Community

我找不到干净的方法,但这里有一个黑客......

1)我注意到 mouseover 事件发生在缩放之前,但缩放发生在 mousedown 或 focus 事件之前。

2) 您可以使用 javascript 动态更改 META 视口标记(请参阅 Enable/disable zoom on iPhone safari with Javascript?

所以,试试这个(在 jquery 中显示的紧凑性):

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

这绝对是一个 hack……在某些情况下,鼠标悬停/向下并不总是捕捉到条目/退出,但它在我的测试中运行良好并且是一个可靠的开始。


不确定 Safari 的行为何时可能发生了变化,但现在(iOS6.0.1)mousedown 发生在自动缩放之前。因此,在我之前的解决方案中,缩放功能很快就会重新启用。我还没有想出一个足够的修复,因为我现在尝试的所有事件都发生在缩放之前。您可以在按键或模糊时重新启用缩放,但在某些情况下这可能会丢失(例如,如果用户想要在开始输入任何内容之前手动缩放)。
p
piouPiouM

我最近(今天:D)不得不整合这种行为。为了不影响包括组合在内的原始设计领域,我选择在该领域的焦点应用转换:

input[type="text"]:focus, input[type="password"]:focus,
textarea:focus, select:focus {
  font-size: 16px;
}

仅供参考,这在我的带有 iOS 6 的 iphone 5 上运行良好,但在带有 iOS 5 的纵向模式的 iphone 4 上,在缩放发生后应用了焦点样式。也许发生了一些微妙的事情,我没有进一步调查。
我只想说我有很多不同的查询使用缩放来加快开发速度,并且取决于您缩放的程度将决定您需要多少字体大小我相信
:focus 不适用于我 iOS 10.2 iPhone 6,但 input[type="text"]:hover 效果很好。
J
Jeffery To

除了简单地将字体大小设置为 16px,您还可以:

设置输入字段的样式,使其大于预期大小,允许将逻辑字体大小设置为 16 像素。使用 scale() CSS 变换和负边距将输入字段缩小到正确的大小。

例如,假设您的输入字段最初的样式为:

input[type="text"] {
    border-radius: 5px;
    font-size: 12px;
    line-height: 20px;
    padding: 5px;
    width: 100%;
}

如果您通过将所有维度增加 16 / 12 = 133.33% 来扩大字段,然后使用 scale() 将其缩小 12 / 16 = 75%,则输入字段将具有正确的视觉大小(和字体大小),并且会有没有放大焦点。

由于 scale() 仅影响视觉大小,您还需要添加负边距以减小字段的逻辑大小。

使用这个 CSS:

input[type="text"] {
    /* enlarge by 16/12 = 133.33% */
    border-radius: 6.666666667px;
    font-size: 16px;
    line-height: 26.666666667px;
    padding: 6.666666667px;
    width: 133.333333333%;

    /* scale down by 12/16 = 75% */
    transform: scale(0.75);
    transform-origin: left top;

    /* remove extra white space */
    margin-bottom: -10px;
    margin-right: -33.333333333%;
}

输入字段的逻辑字体大小为 16 像素,而文本显示为 12 像素。

我有一篇博文,其中我会稍微详细一些,并将此示例作为可查看的 HTML:
No input zoom in Safari on iPhone, the pixel perfect way


M
Meligy

受@jirikuchta 回答的启发,我通过添加以下 CSS 解决了这个问题:

#myTextArea:active {
  font-size: 16px; /* `16px` is safer I assume, although `1rem` works too */
}

没有 JS,我也没有注意到任何闪光或任何东西。

值得注意的是,带有 maximum-scale=1viewport 也可以工作,但当页面作为 iframe 加载时,或者如果您有一些其他脚本修改 viewport 等时则无效。


T
Tuyen Cao

将 user-scalable=0 添加到视口元,如下所示

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

为我工作:)


“确保浏览器缩放缩放不会被页面的视口元元素阻止,以便可以将页面缩放到 200%。应避免此元元素的用户可缩放和最大缩放属性的限制值。” w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
这违反了 W3 定义的可访问性规则。
为我工作,这对我来说也是最好的解决方案,因为我希望可以自由地将输入字体大小更改为 16px 以下并且不想要 JS hack
l
lortschi

这在 iOS Safari 和 Chrome 上对我有用。对于输入选择器,可以设置 class 或 id 以包含当前。

@supports (-webkit-overflow-scrolling: touch) {
   input {
     font-size: 16px;
   }
}

它有帮助,但如何?)
I
Ilkka R.

在 iOS 7 上运行的 Javascript hack。这是基于 @dlo 的回答,但是 mouseover 和 mouseout 事件被 touchstart 和 touchend 事件所取代。基本上,此脚本会在再次启用缩放之前添加半秒超时以防止缩放。

$("input[type=text], textarea").on({ 'touchstart' : function() {
    zoomDisable();
}});
$("input[type=text], textarea").on({ 'touchend' : function() {
    setTimeout(zoomEnable, 500);
}});

function zoomDisable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />');
}
function zoomEnable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=1" />');
} 

这对我来说效果最好。但是,我将 touchstart/touchend 事件更改为一个带有 zoomDisable 和 zoomEnable 的“焦点”事件。
添加延迟似乎在较新版本的 iOS 上运行良好,但有趣的是,它在设置为 250 毫秒时效果不佳。这暗示在某些情况下,500ms 也可能不起作用,但如果它在大多数情况下都有效,我想它总比完全不工作要好。好想法。
佚名

这对我有用:

input, textarea {
    font-size: initial;
}

非常简单,但是有什么方法可以控制“初始”大小是多少?
我还没有测试过,但这应该是一种控制字体大小的方法。 (请让我知道这是否有效,我会更新我的答案) body { font-size: 20px; } 输入 { 字体大小:继承; }
T
Tanny O'Haley

我在上面使用了 Christina 的解决方案,但对引导程序和另一条规则进行了小修改,以适用于台式计算机。 Bootstrap 的默认字体大小是 14px,这会导致缩放。以下将 Bootstrap 中的“表单控件”更改为 16px,以防止缩放。

@media screen and (-webkit-min-device-pixel-ratio:0) {
  .form-control {
    font-size: 16px;
  }
}

对于非移动浏览器,返回 14px。

@media (min-width: 768px) {
  .form-control {
    font-size: 14px;
  }
}

我尝试使用 .form-control:focus,将其保留为 14 像素,但焦点将其更改为 16 像素,但它没有解决 iOS8 的缩放问题。至少在我使用 iOS8 的 iPhone 上,字体大小必须在焦点之前为 16 像素,以便 iPhone 不会缩放页面。


N
Nicolas Hoizey

我这样做了,也使用 jQuery:

$('input[type=search]').on('focus', function(){
  // replace CSS font-size with 16px to disable auto zoom on iOS
  $(this).data('fontSize', $(this).css('font-size')).css('font-size', '16px');
}).on('blur', function(){
  // put back the CSS font-size
  $(this).css('font-size', $(this).data('fontSize'));
});

当然,如果此 16px 字体大小破坏了设计,则可能必须调整界面中的其他一些元素。


这是优雅的。这是风格。我没有双关语了。巧妙的方法。
@Wolfr 您在实际设备上尝试过吗?
这在 iOS 12 上对我们有用。我最喜欢这种方法,而不是胡乱使用 css 转换和负边距。
S
Scott Phillips

:focus 这样的伪元素不再像以前那样工作了。从 iOS 11 开始,可以在您的主要样式之前添加一个简单的重置声明(前提是您不使用较小的字体大小覆盖它们)。

/* Prevent zoom */
select, input, textarea {
  font-size: 16px;
}

值得一提的是,对于诸如 Tachyons.css 之类的 CSS 库,很容易意外地覆盖您的字体大小。

例如 class: f5 等价于: fontSize: 1rem,如果您将正文字体比例保持为默认值,这很好。

但是:如果您选择字体大小类:f6,这将相当于向上小显示器上的 fontSize: .875rem。在这种情况下,您需要更具体地说明您的重置声明:


  /* Prevent zoom */
  select, input, textarea {
    font-size: 16px!important;
  }

@media screen and (min-width: 30em) {

/* not small */

}


j
jirikuchta

经过一段时间的尝试,我想出了这个解决方案

// set font-size to 16px to prevent zoom 
input.addEventListener("mousedown", function (e) {
  e.target.style.fontSize = "16px";
});

// change font-size back to its initial value so the design will not break
input.addEventListener("focus", function (e) {
  e.target.style.fontSize = "";
});

在“mousedown”上,它将输入的字体大小设置为 16px。这将防止缩放。在焦点事件中,它会将字体大小更改回初始值。

与之前发布的解决方案不同,这将使您可以将输入的字体大小设置为您想要的任何内容。


这实际上对我有用,特别是因为在较新的 iOS 版本中,您不能使用视口元标记来禁用缩放。
l
l3bel

在阅读了这里的几乎每一行并测试了各种解决方案之后,感谢所有分享他们的解决方案的人,这是我在 iPhone 7 iOS 10.x 上想出、测试并为我工作的:

@media screen and (-webkit-min-device-pixel-ratio:0) {
    input[type="email"]:hover,
    input[type="number"]:hover,
    input[type="search"]:hover,
    input[type="text"]:hover,
    input[type="tel"]:hover,
    input[type="url"]:hover,
    input[type="password"]:hover,
    textarea:hover,
    select:hover{font-size: initial;}
}
@media (min-width: 768px) {
    input[type="email"]:hover,
    input[type="number"]:hover,
    input[type="search"]:hover,
    input[type="text"]:hover,
    input[type="tel"]:hover,
    input[type="url"]:hover,
    input[type="password"]:hover,
    textarea:hover,
    select:hover{font-size: inherit;}
}

但是,它有一些缺点,由于在“悬停”和“聚焦”状态之间发生的快速字体大小变化,以及重绘对性能的影响,导致明显的“跳跃”


感谢您的反馈,@MikeBoutin。你能分享你的环境(设备/iOS版本)吗?
A
Amey Vartak

我查看了多个答案。\

在元标记中设置 maximum-scale=1 的答案在 iOS 设备上运行良好,但在 Android 设备上禁用捏合缩放功能。设置 font-size: 16px; onfocus 对我来说太老套了。

所以我写了一个JS函数来动态改变meta标签。

var iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
if (iOS)
    document.head.querySelector('meta[name="viewport"]').content = "width=device-width, initial-scale=1, maximum-scale=1";
else
    document.head.querySelector('meta[name="viewport"]').content = "width=device-width, initial-scale=1";

S
Spellcoder

我不得不“修复”荷兰大学网站的自动放大表单控件问题(在表单控件中使用 15px)。我提出了以下一组要求:

用户必须仍然能够放大

字体大小必须保持不变

没有临时不同的造型闪烁

没有 jQuery 要求

必须在最新的 iOS 上工作,并且不妨碍任何其他操作系统/设备组合

如果可能没有魔法超时,如果需要正确清除计时器

到目前为止,这是我想出的:

/*
NOTE: This code overrides the viewport settings, an improvement would be
      to take the original value and only add or change the user-scalable value
*/

// optionally only activate for iOS (done because I havn't tested the effect under other OS/devices combinations such as Android)
var iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)
if (iOS)
  preventZoomOnFocus();


function preventZoomOnFocus()
{
  document.documentElement.addEventListener("touchstart", onTouchStart);
  document.documentElement.addEventListener("focusin", onFocusIn);
}


let dont_disable_for = ["checkbox", "radio", "file", "button", "image", "submit", "reset", "hidden"];
//let disable_for = ["text", "search", "password", "email", "tel", "url", "number", "date", "datetime-local", "month", "year", "color"];


function onTouchStart(evt)
{
  let tn = evt.target.tagName;

  // No need to do anything if the initial target isn't a known element
  // which will cause a zoom upon receiving focus
  if (    tn != "SELECT"
      &&  tn != "TEXTAREA"
      && (tn != "INPUT" || dont_disable_for.indexOf(evt.target.getAttribute("type")) > -1)
     )
    return;

  // disable zoom
  setViewport("width=device-width, initial-scale=1.0, user-scalable=0");
}

// NOTE: for now assuming this focusIn is caused by user interaction
function onFocusIn(evt)
{
  // reenable zoom
  setViewport("width=device-width, initial-scale=1.0, user-scalable=1");
}

// add or update the <meta name="viewport"> element
function setViewport(newvalue)
{
  let vpnode = document.documentElement.querySelector('head meta[name="viewport"]');
  if (vpnode)
    vpnode.setAttribute("content",newvalue);
  else
  {
    vpnode = document.createElement("meta");
    vpnode.setAttribute("name", "viewport");
    vpnode.setAttribute("content", newvalue);
  }
}

一些注意事项:

请注意,到目前为止,我只在 iOS 11.3.1 上对其进行了测试,但很快会在其他几个版本上进行测试

使用 focusIn 事件意味着它至少需要 iOS 5.1(但我认为我们构建的网站在 iOS 9 之前的版本中运行是一个很酷的奖励)

使用事件委托,因为我工作的很多网站都有可能动态创建表单控件的页面

将 eventListeners 设置为 html 元素 (documentElement),以便不必等待 body 可用(不想费心检查文档是否已准备好/已加载状态或需要等待 DOMContentLoaded 事件)


这对我来说并不完全完美(当用户按下按钮时, 会触发输入缩放),但它适用于我 85% 的情况,目前已经足够好了。只是想感谢您分享您的解决方案!
J
JBlitzen

即使有了这些答案,我也花了三天时间才弄清楚发生了什么,将来我可能再次需要解决方案。

我的情况与描述的情况略有不同。

在我的页面中,我在 div 中有一些内容可编辑的文本。当用户单击不同的 div 时,我自动选择了 contenteditable div 中的一些文本(先前已保存并清除的选择范围),在该选择上运行富文本 execCommand,然后再次清除它。

这使我能够根据用户与页面上其他地方的颜色 div 的交互来无形地更改文本颜色,同时保持选择通常隐藏以让他们在适当的上下文中看到颜色。

好吧,在 iPad 的 Safari 上,单击颜色 div 会导致屏幕键盘出现,而我所做的一切都无法阻止它。

我终于弄清楚了 iPad 是如何做到这一点的。

它侦听触发选择可编辑文本的 touchstart 和 touchend 序列。

当这种组合发生时,它会显示屏幕键盘。

实际上,它会在放大可编辑文本的同时扩展底层页面。我花了一天的时间才明白我所看到的。

所以我使用的解决方案是在那些特定的颜色 div 上拦截 touchstart 和 touchend 。在这两个处理程序中,我停止传播和冒泡并返回 false。但是在 touchend 事件中,我触发了与单击触发相同的行为。

因此,在此之前,Safari 会触发我认为的“touchstart”、“mousedown”、“touchend”、“mouseup”、“click”,并且由于我的代码,按此顺序进行了文本选择。

由于截距的新序列只是文本选择。在 Safari 处理它并执行它的键盘操作之前,其他所有内容都会被拦截。 touchstart 和 touchend 拦截也阻止了鼠标事件的触发,在上下文中这完全没问题。

我不知道用更简单的方法来描述这个问题,但我认为把它放在这里很重要,因为我在第一次遇到这个问题后的一个小时内就找到了这个帖子。

我 98% 确定相同的修复程序适用于输入框和其他任何东西。拦截触摸事件并单独处理它们,不要让它们传播或冒泡,并考虑在短暂的超时后进行任何选择,以确保 Safari 不会将序列识别为键盘触发器。


这是对 safari 正在做什么的一个很好的解释。谢谢!
j
jonhobbs

2021解决方案...

好的,我已经阅读了所有旧答案,但没有一个对我有用。经过数小时尝试不同的事情后,最终解决方案似乎很简单。

input{
    transform: scale(0.875);
    transform-origin: left center;
    margin-right: -14.28%;
}

在 PC 上的 iOS/Android/Chrome 上测试

这允许您使用 14px 字体,如果您需要不同的大小,则缩放因子为 14/16 = 0.875,负边距为 (1 - 0.875) / 0.875 * 100

我的输入有一个父级设置为“display:flex”,它增长到适合父级,因为它有“flex:1 1 auto”。您可能需要也可能不需要这个,但为了完整起见,我将其包括在内。


C
Community

基于 Stephen Walsh's answer... 此代码在不改变焦点输入的字体大小的情况下工作(看起来很蹩脚),而且它仍然适用于 FastClick,我建议将其添加到所有移动网站以帮助带来“活泼” .调整您的“视口宽度”以满足您的需要。

// disable autozoom when input is focused
    var $viewportMeta = $('head > meta[name="viewport"]');
    $('input, select, textarea').bind('touchend', function(event) {
        $viewportMeta.attr('content', 'width=640, user-scalable=0');
        setTimeout(function(){ $viewportMeta.attr('content', 'width=640, user-scalable=1'); }, 1)
    });

如果用户在单击输入控件之前已经放大了一点,这个解决方案会导致视口突然“取消缩放”吗?
是的,确实如此,但它看起来并不比之前每次用户单击输入时发生的“缩放”效果更刺耳。
n
net.uk.sweet

我看到这里的人们使用 JavaScript 或视口功能做了一些奇怪的事情,并关闭了设备上的所有手动缩放功能。在我看来,这不应该是一个解决方案。添加此 CSS 片段将关闭 iOS 中的自动缩放,而无需将字体大小更改为固定数字,例如 16px。

默认情况下,我在输入字段中使用 93.8% (15px) 的字体大小,并通过添加我的 CSS 片段保持在 93.8%。无需更改为 16px 或使其成为固定数字。

input[type="text"]:focus,
textarea:focus {
    -webkit-text-size-adjust: 100%;
}

这对我不起作用,已使用最新的 iOS 6 和 iOS 9.2.1 进行了测试。这是一个最小的可重现页面:pastebin.com/bh5Zhe9h 它仍然放大焦点。奇怪的是,这是在 2015 年发布的,但在 iOS 6 中却不起作用。
s
sindiploma

将字体大小(用于输入字段)设置为等于正文的字体大小,似乎可以防止浏览器缩小或缩小。我建议使用 font-size: 1rem 作为更优雅的解决方案。


B
Bohdan Vorona

顺便说一句,如果你使用 Bootstrap,你可以只使用这个变体:

.form-control {
  font-size: 16px;
}

A
Adrien Castagliola

在 Angular 中,您可以使用指令来防止对 IOS 设备的焦点进行缩放。没有元标记来保持可访问性。

import { Directive, ElementRef, HostListener } from '@angular/core';

const MINIMAL_FONT_SIZE_BEFORE_ZOOMING_IN_PX = 16;

@Directive({ selector: '[noZoomiOS]' })

export class NoZoomiOSDirective {
  constructor(private el: ElementRef) {}

@HostListener('focus')
  onFocus() {
    this.setFontSize('');
  }

@HostListener('mousedown')
  onMouseDown() {
    this.setFontSize(`${MINIMAL_FONT_SIZE_BEFORE_ZOOMING_IN_PX}px`);
  }

private setFontSize(size: string) {
  const { fontSize: currentInputFontSize } = window.getComputedStyle(this.el.nativeElement, null);

  if (MINIMAL_FONT_SIZE_BEFORE_ZOOMING_IN_PX <= +currentInputFontSize.match(/\d+/)) {
      return;
   }

  const iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
  iOS 
     && (this.el.nativeElement.style.fontSize = size);
 }
}

在您的 *.module.ts 中声明它之后,您可以像这样使用它 <input noZoomiOS >