【问题标题】:disable viewport zooming iOS 10+ safari?禁用视口缩放 iOS 10+ safari?
【发布时间】:2016-10-14 23:02:06
【问题描述】:

我已经将我的 iPhone 6 plus 更新到 iOS 10 测试版,并且刚刚发现在移动 safari 中,您可以通过双击或捏忽略元中的 user-scalable=no 代码来缩放任何网页标签。不知道是bug还是功能。如果将其视为一项功能,我们如何禁用视口缩放 iOS 10 safari ?


在 iOS 11/12 版本上进行了更新,iOS 11 和 iOS 12 Safari 仍然尊重user-scalable=no 元标记。

【问题讨论】:

  • 一项辅助功能:在 iOS 10 上的 Safari 中值得注意twitter.com/thomasfuchs/status/742531231007559680/photo/1
  • 不,不是。对于普通的 Web 内容,这是不好的做法。对于 Web 应用程序,默认的缩放行为会完全破坏可用性。例如,没有人想放大频道向上按钮,因为他们点击了两次,也没有人想放大视频游戏的一部分,因为他们点击了两次跳转按钮。最初添加此功能是有原因的,仅仅因为一些“网页设计师”不知道他们在做什么而破坏每个人的可用性是没有意义的。冲着网站设计师大喊大叫,别再破坏浏览器了。
  • 说它是“不好的做法”是一种观点,并不能改变这样一个事实:Apple 坚持采用网络标准,社区花费数月/数年/数十年时间来实现跨平台并接受一个巨大的废话在他们。为什么苹果要规定网页设计师不知道他们在做什么?可怕的争论。
  • 就个人而言,我认为这源于在线样板代码,开发人员只是盲目地复制和粘贴,而不知道代码的目的是什么。
  • 答案很简单,Apple:将禁用元标记设为默认关闭的可访问性设置。需要的人会得到,不需要的人不会受到惩罚。

标签: mobile-safari ios10 ios11 viewport ios12


【解决方案1】:

在 iOS 10 上的 Safari 浏览器中可以防止网页缩放,但这需要您做更多的工作。我猜的论点是,一定程度的难度应该阻止货物狂热的开发人员将“user-scalable=no”放入每个视口标签,并使视力受损的用户不必要地困难。

不过,我希望看到 Apple 改变他们的实现,以便有一种简单的(元标记)方法来禁用双击缩放。大多数困难都与这种互动有关。

您可以通过以下方式停止捏合缩放:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, false);

请注意,如果任何更深层次的目标对事件调用 stopPropagation,事件将不会到达文档,并且此侦听器不会阻止缩放行为。

禁用双击缩放是类似的。您禁用在前一次点击后 300 毫秒内发生的对文档的任何点击:

var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
  var now = (new Date()).getTime();
  if (now - lastTouchEnd <= 300) {
    event.preventDefault();
  }
  lastTouchEnd = now;
}, false);

如果您没有正确设置表单元素,则专注于输入将自动缩放,并且由于您已大部分禁用手动缩放,因此现在几乎不可能取消缩放。确保输入字体大小 >= 16px。

如果您尝试在本机应用程序的 WKWebView 中解决此问题,上面给出的解决方案是可行的,但这是一个更好的解决方案:https://stackoverflow.com/a/31943976/661418。正如其他答案中提到的,在 iOS 10 beta 6 中,Apple 现在提供了一个标志来尊重元标记。

2017 年 5 月更新:我用更简单的“在 touchmove 上检查 event.scale”方法替换了旧的“在 touchstart 上检查触摸长度”禁用捏合缩放的方法。应该对每个人都更可靠。

【讨论】:

  • 请注意,touchstart hack 是不一致的......如果你设法回避它,你就会陷入非常不舒服的状态
  • 例如。全屏地图应用程序,在地图应用程序(Google Maps JS、Leaflet 等)中有一个硬编码的缩放功能。谷歌建议添加元标记&lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no" /&gt;,如果浏览器不尊重元标记,这是非常糟糕的浏览器设计。另一个非常糟糕的设计是通过滑动进行的后退/前进动作,这在 iOS 9/10 中是无法阻止的。它严重破坏了 Web 应用程序中的拖动操作。
  • 如果用户开始用一根手指拖动然后将第二根手指放在屏幕上将能够捏合缩放。您可以在touchmove 上使用preventDefault 禁用缩放和滚动。您不能(完全)在不禁用滚动的情况下禁用缩放。
  • 哇,这部分(我会粘贴在这里)对我很有帮助。我在互联网上的任何地方都没有看到其他人提到过这一点。我花了几个小时来解决这个问题。我对 Apple 的 UX 设计选择感到非常失望,它会自动放大但不会缩小。 If you don't set up your form elements right, focusing on an input will auto-zoom, and since you have mostly disabled manual zoom, it will now be almost impossible to unzoom. Make sure the input font size is &gt;= 16px.
  • 这似乎不再适用于 iOS 12。知道如何让它适用于 iOS 12 吗?
【解决方案2】:

这是 iOS 10 中的一项新功能。

来自 iOS 10 beta 1 发行说明:

  • 为了提高 Safari 中网站的可访问性,即使网站在视口中设置了 user-scalable=no,用户现在也可以捏合缩放。

我希望我们很快就会看到一个 JS 插件以某种方式禁用它。

【讨论】:

  • @Onza:我不认为这很糟糕。我认为这很好。禁用捏/缩放(默认用户行为)被认为是不好的,许多移动网站都这样做。唯一可接受的用户案例是外观和感觉都像应用程序的真实网络应用程序。
  • Bad.. 我使用 js 更改视口并仅在网站上选择某些元素时阻止缩放,现在由于此“决定”而损坏。如果有人决定阻止它 - 这是有原因的。
  • @Karlth 非常适合游戏开发者
  • 我有 IOS 10.0.2,user-scalable=no 在我们的网站上不再禁用缩放...我们缩放的主要问题是我们固定的侧边菜单。它只是破坏了布局。 . 对此有任何想法或解决方案吗?我知道缩放有利于可访问性,我们使用 js 事件(锤子)和 css 在我们网站的特定部分提供了缩放功能。我不明白为什么必须对每个人都施加规则,好像 PC 警察开始了也接管我们的开发世界?!
  • “唯一可接受的用户案例是外观和感觉都像应用程序的真实 Web 应用程序。” - 就像你说的,这是一个真实的、可接受的用例,它并不那么罕见..
【解决方案3】:

我已经能够在单个元素上使用touch-action css 属性来解决这个问题。尝试在链接或按钮等经常被点击的元素上设置touch-action: manipulation;

【讨论】:

  • “manipulation”不会阻止捏缩放,只能双击缩放。
  • 这应该是公认的答案。你可以使用touch-action: none;来自己控制所有的手势。
  • 这很棒 - 禁用双击缩放,同时保持捏缩放,这应该被视为一种手势 - 双击不应该。 1 条狗是一条狗。 1 条狗 + 1 条狗不是航天飞机制造的。它制造了 2 只狗,它们会做你期望 2 只狗会做的事情。我从没想过2条狗会成为航天飞机。从不。
  • @GuySopher iOS 确实提供touch-action: nonemanipulatoin,这使得捏缩放问题保持原样。
  • 使用触摸动作:pan-x pan-y,修复它。
【解决方案4】:

目前在 Mobile Safari 中有效的解决方法是将 addEventListener 中的第三个参数设为 { passive: false },因此完整的解决方法如下所示:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

您可能希望check if options are supported 保持向后兼容。

【讨论】:

  • 有人在 iOS 12 上试过这个吗?我添加了上面的代码,它对我的​​ webapp 没有任何作用。仍然能够放大这个愚蠢的 Safari。我的元视口标签看起来像这样:&lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"&gt;.
  • @PatrickDaVader 是的,找不到适用于 iOS 12 Safari 的任何有效解决方案。不停的缩放让晕船。
  • 这个适用于 iOS 13。我的 标签包括:&lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" /&gt;&lt;meta name="HandheldFriendly" content="true"&gt;
  • @SterlingBourne 复制了您的设置。确实有效,但只有 90% 的时间。不知道为什么不是一直。
  • @SterlingBourne 响应对我有用!谢谢。他应该将其发布为答案而不是评论,以便对其进行投票
【解决方案5】:

这种行为似乎在最新的 beta 版中有所改变,在撰写本文时是 beta 6。

来自 iOS 10 Beta 6 的发行说明:

WKWebView 现在默认从视口尊重user-scalable=noWKWebView 的客户可以提高可访问性并允许用户 通过设置WKWebViewConfiguration 在所有页面上进行捏合缩放 属性ignoresViewportScaleLimitsYES

但是,在我的(非常有限的)测试中,我还不能确认是这种情况。

编辑:已验证,iOS 10 Beta 6 默认尊重user-scalable=no

【讨论】:

  • 10.0.1 在这里。不尊重它。苹果摆脱了每个人都需要的功能是什么原因..
  • 这是指WKWebView 不是 Safari。资料来源:我们的一个地图应用程序坏了,我们知道如何修复它。
  • 啊哈!抱歉,我在WKWebView 中寻找相同错误/功能的解决方案时来到这里,并且在写我的答案时假设原始问题询问了WKWebView。所以我想在第一个 beta 版本中,Apple 改变了 WKWebView 和移动 Safari 的行为,然后在 beta 6 中,他们恢复了 WKWebView 的行为,但保留了移动 Safari。
  • 10.0.2 不尊重user-scalable=no。我不知道他们为什么要撤消这个,只是为了把它带回来,只是为了再次删除它。
【解决方案6】:

我花了大约一个小时寻找更强大的 javascript 选项,但没有找到。碰巧在过去的几天里,我一直在摆弄hammer.js(Hammer.js 是一个可以让你轻松操作各种触摸事件的库),而且大部分时间都没有完成我想做的事情。

有了这个警告,并且理解我绝不是 javascript 专家,这是我想出的一个解决方案,它基本上利用hammer.js 来捕获捏缩放和双击事件,然后记录并丢弃它们。

确保在页面中包含hammer.js,然后尝试将此javascript 粘贴在头部某处:

< script type = "text/javascript" src="http://hammerjs.github.io/dist/hammer.min.js"> < /script >
< script type = "text/javascript" >

  // SPORK - block pinch-zoom to force use of tooltip zoom
  $(document).ready(function() {

    // the element you want to attach to, probably a wrapper for the page
    var myElement = document.getElementById('yourwrapperelement');
    // create a new hammer object, setting "touchAction" ensures the user can still scroll/pan
    var hammertime = new Hammer(myElement, {
      prevent_default: false,
      touchAction: "pan"
    });

    // pinch is not enabled by default in hammer
    hammertime.get('pinch').set({
      enable: true
    });

    // name the events you want to capture, then call some function if you want and most importantly, add the preventDefault to block the normal pinch action
    hammertime.on('pinch pinchend pinchstart doubletap', function(e) {
      console.log('captured event:', e.type);
      e.preventDefault();
    })
  });
</script>

【讨论】:

  • 我在使用hammer.js 时也一直在尝试解决这个问题,并且可以确认我可以通过向所有锤子手势处理程序添加.preventDefault 来防止视口缩放。我正在同时使用滑动/捏合/平移/点击,我已将其添加到所有处理程序中,我不知道是否有特定的处理程序在做这项工作。
【解决方案7】:

使用“touch-action: pan-x pan-y”禁用“双指缩放”和“双击缩放”。它适用于我测试过的所有触摸屏/手机,包括 iOS Safari 14.5.1。

body {
  touch-action: pan-x pan-y;
}

【讨论】:

  • 当今最佳答案。效果很好。
  • 它不是在可滚动元素上工作,而是在不可滚动元素上工作,什么是可伸缩的解决方案来避免可滚动元素的这个问题
  • iOS 15 完美无瑕
【解决方案8】:

我们可以通过注入一个样式规则和拦截缩放事件来获得我们想要的一切:

$(function () {
  if (!(/iPad|iPhone|iPod/.test(navigator.userAgent))) return
  $(document.head).append(
    '<style>*{cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}</style>'
  )
  $(window).on('gesturestart touchmove', function (evt) {
    if (evt.originalEvent.scale !== 1) {
      evt.originalEvent.preventDefault()
      document.body.style.transform = 'scale(1)'
    }
  })
})

✔ 禁用捏缩放。

✔ 禁用双击缩放。

✔ 滚动不受影响。

✔ 禁用点击突出显示(在 iOS 上由样式规则触发)。

注意:根据自己的喜好调整 iOS 检测。更多关于 here.


lukejacksonPiotr Kowalski 道歉,他们的答案以修改后的形式出现在上面的代码中。

【讨论】:

  • 这适用于我运行 iOS 11.2 的 iPad 模拟器。在我运行 iOS 11.3 的真实 iPad 上,它不起作用。我添加了一个 console.log 以确保事件被触发并出现在控制台中。这与iOS 11.3有关吗?还是使用真实设备?
  • @MathieuR。这是 iOS 11.3 的问题。可以通过使用基于addEventListener 的答案之一并将{ passive: false } 作为options 参数而不是false 传递来纠正它。但是,为了向后兼容,您需要传递 false,除非支持 passive 选项字段。见developer.mozilla.org/en-US/docs/Web/API/EventTarget/…
  • @JoshGallagher 你能提供一个可行的例子吗?在 iOS11 上,没有一个答案对我有用。
  • 'gesturestart' -> preventDefault 在 iOS 12,2 上对我有效
【解决方案9】:

在我的特殊情况下,我正在使用 Babylon.js 创建一个 3D 场景,我的整个页面由一个全屏画布组成。 3D 引擎有自己的缩放功能,但在 iOS 上,捏缩放会干扰这一点。我更新了@Joseph 的答案来解决我的问题。要禁用它,我发现我需要将 {passive: false} 作为选项传递给事件侦听器。以下代码适用于我:

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);

【讨论】:

  • 我的用例也是一个带有自定义捏合控制的整页 3d 场景。如果没有解决方法让 Apple 明确忽略用户规模:没有元数据,我会沉没。
  • Life-saver - 这是从 iOS 14.4.2 开始对我有用的唯一解决方案,它仍然允许注册多点触控 - 我的用例是一个使用操纵杆控制的网络游戏移动。
【解决方案10】:

我尝试了上一个关于捏合缩放的答案

document.documentElement.addEventListener('touchstart', function (event) {
    if (event.touches.length > 1) {
        event.preventDefault();
    }
}, false);

但有时当 event.touches.length > 1 时屏幕仍会缩放 我发现最好的方法是使用 touchmove 事件,以避免任何手指在屏幕上移动。代码将是这样的:

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();      
}, false);

希望它会有所帮助。

【讨论】:

  • 这只有在你的应用非常适合的情况下才有效……如果你有可滚动的内容,它就不起作用……在某些情况下仍然不错。
  • 这甚至会禁用网站上的滚动.. 不好
  • @eljamz 感谢您告诉我,是的..我的应用非常适合屏幕显示。
  • @Gags 我还没有测试滚动功能,谢谢告知。
【解决方案11】:

检查 touchove 事件中的比例因子,然后阻止触摸事件。

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);

【讨论】:

  • iOS 13 将 false 改为 {passive: false}
【解决方案12】:

我想出了一个非常幼稚的解决方案,但它似乎有效。 我的目标是防止意外的双击被解释为放大,同时保持捏缩放工作以实现可访问性。

这个想法是通过双击测量第一个touchstart 和第二个touchend 之间的时间,然后如果延迟太小,则将最后一个touchend 解释为点击。在防止意外缩放的同时,这种方法似乎使列表滚动不受影响,这很好。不知道我是否没有错过任何东西。

let preLastTouchStartAt = 0;
let lastTouchStartAt = 0;
const delay = 500;

document.addEventListener('touchstart', () => {
  preLastTouchStartAt = lastTouchStartAt;
  lastTouchStartAt = +new Date();
});
document.addEventListener('touchend', (event) => {
  const touchEndAt = +new Date();
  if (touchEndAt - preLastTouchStartAt < delay) {
    event.preventDefault();
    event.target.click();
  }
});

灵感来自 gist from mutewinterJoseph's answer

【讨论】:

    【解决方案13】:

    根据要求,我已将我的评论转移到一个答案中,以便人们对其进行投票:

    这在 iOS 13 上 90% 的时间都有效:

    &lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" /&gt;

    &lt;meta name="HandheldFriendly" content="true"&gt;

    【讨论】:

    • 为什么这在 90% 的时间里都有效?我在我的身上试过了,但没有用:(
    【解决方案14】:

    尽管听起来很奇怪,至少对于 iOS 10.2 中的 Safari,如果您的元素或其任何祖先具有以下任一情况,双击缩放会神奇地被禁用:

    1. 一个 onClick 监听器 - 它可以是一个简单的 noop。
    2. cursor: pointer 在 CSS 中设置

    【讨论】:

    • 捏一下怎么样?
    • 不幸的是,这个解决方案不包括捏到缩放。为此,我们使用了以下建议的解决方案:stackoverflow.com/a/39594334/374196
    • 对我不起作用。我正在使用此测试页在 iPod Touch 上使用 10.2.1 Beta 4,并双击任何灰色正方形缩放:jsbin.com/kamuta/quiet
    • 我在 react 应用程序的 span 上有这个,但它不起作用。
    【解决方案15】:

    无意的缩放往往发生在以下情况:

    • 用户双击界面组件
    • 用户使用两个或多个数字(捏合)与视口进行交互

    为了防止 双击 行为,我找到了两个非常简单的解决方法:

    <button onclick='event.preventDefault()'>Prevent Default</button>
    <button style='touch-action: manipulation'>Touch Action Manipulation</button>
    

    这两种方法都可以防止 Safari (iOS 10.3.2) 在按钮上放大。如您所见,一种仅是 JavaScript,另一种仅是 CSS。适当使用。

    这是一个演示:https://codepen.io/lukejacksonn/pen/QMELXQ

    我还没有尝试阻止捏合行为(目前),主要是因为我倾向于不为 Web 创建多点触控界面,其次我已经意识到可能所有界面(包括本机应用程序 UI)都应该是“捏合”可以在某些地方进行缩放。我仍然会设计避免用户不得不这样做以使他们不惜一切代价访问您的 UI。

    【讨论】:

      【解决方案16】:

      发现这个简单的解决方法似乎可以防止双击缩放:

          // Convert touchend events to click events to work around an IOS 10 feature which prevents
          // developers from using disabling double click touch zoom (which we don't want).
          document.addEventListener('touchend', function (event) {
              event.preventDefault();
              $(event.target).trigger('click');
          }, false);
      

      【讨论】:

        【解决方案17】:

        在当前版本的 Safari 中,这不再有效。您必须通过传递 {passiv:false}

        将第二个参数定义为非被动
         document.addEventListener('touchmove', function(e) {
         e.preventDefault();
        }, { passive: false });
        

        【讨论】:

        • 在 iOS 14.4 上测试:它禁用视口的触摸滚动,因此您无法再上下滚动页面。
        【解决方案18】:

        我在 iOS(iPhone 6、iOS 10.0.2)上的页面上检查了上述所有答案,但没有成功。这是我的工作解决方案:

        $(window).bind('gesturestart touchmove', function(event) {
            event = event.originalEvent || event;
            if (event.scale !== 1) {
                 event.preventDefault();
                 document.body.style.transform = 'scale(1)'
            }
        });
        

        【讨论】:

        • 不幸的是,这仅适用于您的页面非常适合,而不是当您有可滚动内容时
        • 嗯。根据我的经验(iOS 10.3),这适用于可滚动内容。
        【解决方案19】:

        这对我有用:

        document.documentElement.addEventListener('touchmove', function (event) {
            event.preventDefault();
        }, false);
        

        【讨论】:

        • 我试过这个,它确实阻止了捏缩放,但是它禁用了视口的触摸滚动,所以你不能再上下滚动页面了。
        猜你喜欢
        • 2017-08-30
        • 2017-02-04
        • 2018-12-05
        • 2011-05-22
        • 2018-02-03
        • 2020-02-19
        • 2020-05-01
        • 1970-01-01
        • 2016-10-03
        相关资源
        最近更新 更多