ChatGPT解决这个技术问题 Extra ChatGPT

光标外的 iOS 11 Safari 引导模式文本区域

在 iOS 11 Safari 中,输入文本框光标位于输入文本框之外。我们不明白为什么会出现这个问题。如您所见,我的重点文本框是电子邮件文本输入,但我的光标在它之外。这只发生在 iOS 11 Safari 上

https://i.stack.imgur.com/34d6d.png

这是 Safari 的一个错误。 Apple 已在内部对其进行了修复,但尚未在 iOS 的公开(甚至测试版)版本中进行修复。 bugs.webkit.org/show_bug.cgi?id=176896

J
Jen Person

我通过在打开模式时将 position:fixed 添加到正文来解决此问题。希望这会帮助你。


请注意下面的每个答案-当模态打开时,Bootstrap 将 .modal-open 添加到正文,因此您可以简单地将 position:fixed 添加到该类。
您可能还需要添加 width:100% 以将主体宽度限制为设备宽度。在某些情况下,根据现有的标记,这可能是一个问题。我也喜欢@gentleboy(下)的解决方案,以免在没有问题的情况下惩罚其他浏览器,因为当将正文设置为固定时会导致正文滚动到顶部,这有点烦人。
奇怪的是,我在使用流星科尔多瓦构建应用程序时遇到了这个问题。似乎任何运行 v11+ 的 iOS 设备都有这个问题。就我而言,我已经将 position:fixed 应用于应用程序的主体。相反,我在 html 元素上将其更改为 position:absolute 并解决了我的问题。谢谢珍!
这可能是我们模式形式的终结。即使 Apple 解决了这个问题,用户也需要更新他们的设备以查看工作表单。没有更简单的通用方法来解决这个问题吗?多填充呢?
你救了我的命<3
M
Mike Casan Ballester

就个人而言,position: fixed 自动滚动到顶部。很烦人!

为避免惩罚其他设备和版本,我仅将此修复应用于适当的 iOS 版本。

**版本 1 - 所有模式修复**

对于 javascript/jQuery

$(document).ready(function() {

    // Detect ios 11_x_x affected  
    // NEED TO BE UPDATED if new versions are affected
    var ua = navigator.userAgent,
    iOS = /iPad|iPhone|iPod/.test(ua),
    iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);

    // ios 11 bug caret position
    if ( iOS && iOS11 ) {

        // Add CSS class to body
        $("body").addClass("iosBugFixCaret");

    }

});

对于 CSS

/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }

**版本 2 - 仅限选定的模态**

我将函数修改为仅针对具有 .inputModal 类的选定模式触发

只有带有输入的模态应该受到影响以避免滚动到顶部。

对于 javascript/jQuery

$(document).ready(function() {

    // Detect ios 11_x_x affected
    // NEED TO BE UPDATED if new versions are affected 
    (function iOS_CaretBug() {

        var ua = navigator.userAgent,
        scrollTopPosition,
        iOS = /iPad|iPhone|iPod/.test(ua),
        iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);

        // ios 11 bug caret position
        if ( iOS && iOS11 ) {

            $(document.body).on('show.bs.modal', function(e) {
                if ( $(e.target).hasClass('inputModal') ) {
                    // Get scroll position before moving top
                    scrollTopPosition = $(document).scrollTop();

                    // Add CSS to body "position: fixed"
                    $("body").addClass("iosBugFixCaret");
                }
            });

            $(document.body).on('hide.bs.modal', function(e) {
                if ( $(e.target).hasClass('inputModal') ) {         
                    // Remove CSS to body "position: fixed"
                    $("body").removeClass("iosBugFixCaret");

                    //Go back to initial position in document
                    $(document).scrollTop(scrollTopPosition);
                }
            });

        }
    })();
});

对于 CSS

/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }

对于 HTML 将类 inputModal 添加到 modal

<div class="modal fade inputModal" tabindex="-1" role="dialog">
    ...
</div>

注意 javascript 函数现在是自调用的

**更新 iOS 11.3 - 修正错误😃🎉 **

从 iOS 11.3 开始,该错误已得到纠正。无需在 iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua); 中测试 OS 11_

但要小心,因为 iOS 11.2 仍在广泛使用(截至 2018 年 4 月)。看

stat 1

stat 2


不错的建议。我没有这个问题,但我想这可能是全球性的答案。我会在我喝完啤酒后添加它
@gentleboy 为什么不使用正则表达式来查找任何 OS 11?这样您就不必将每个 OS 11 更新更新到您的代码?像这样iOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
@RonakK 根据 bugs.webkit.org,它看起来仍然存在于 beta 11.2 和 11.3 中
@T.Evans 正则表达式不起作用。正确的正则表达式可能是这样的:ios11 = /OS 11_(\d{1,2})/.test(ua);
固定位置仍会将文档/正文滚动到顶部。我建议在模态打开时获取当前 scrollTop 位置,并在模态关闭后读取 scrollTop 值。喜欢这个jsfiddle.net/im4aLL/hmvget9x/1
E
Eric Shawn

这个问题不仅限于 Bootstrap,也不仅仅是 Safari。这是 iOS 11 中所有浏览器中出现的一个完整显示错误。上述修复并未在所有情况下都解决此问题。

该错误在此处详细报告:

https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8

据说他们已经将它作为一个错误报告给了苹果。


这似乎是我的问题,在更新到 IOS 11 之前工作正常。Android 用户没有问题。
S
Scott David Murphy

令人沮丧的错误,感谢您识别它。否则,我会把我的 iPhone 或头撞到墙上。

最简单的解决方法是(更改 1 行代码):

只需将以下 CSS 添加到 html 或外部 css 文件。

<style type="text/css">
.modal-open { position: fixed; }
</style>

这是一个完整的工作示例:

.modal-open { 位置:固定; } ...更多按钮...

<脚本 src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js">

我在这里提交了一个问题:https://github.com/twbs/bootstrap/issues/24059


这应该是答案。当模态可见时,Bootstrap 将 modal-open 类添加到正文中。你只需要定位那个类。
我处理这个问题已经有一段时间了。这个解决方案对我来说是不够的,因为添加位置固定会将页面滚动回顶部。因此,当用户关闭模式时,它们处于不同的滚动位置。这会导致糟糕的用户体验
此修复适用于我在移动设备上使用 Chrome。起初很困惑,因为 .modal-open 没有出现在模态 html 中,但我还是将它作为 CSS 添加到我的标题中并且它起作用了。
l
lfkwtz

最简单/最干净的解决方案:

body.modal-open { position: fixed; width: 100%; }

这是最简单的解决方案,并且有效,但唯一的问题是光标完全消失了。它没有最初的情况那么糟糕,但存在可用性问题。
奇怪,我没有遇到光标消失的情况
我也经历过消失的光标,关于为什么会发生这种情况的任何想法?
是的,我还看到第一个焦点事件的光标消失了。后续输入焦点会出现光标。很奇怪。这只发生在 iOS 上的 Safari 中。
@DevinWalker 你们有没有解决过光标消失的问题?
p
piet.t

将您的苹果设备更新到 iOS 11.3 后,此问题不再重现


你是什么意思,Apple修复了它?
@Starscream 是的,苹果用这个软件版本(iOS 11.3)修复了它
A
Anuruk S.

模式打开时将 position: fixed; 添加到 body

$(document).ready(function($){ $("#myBtn").click(function(){ $("#myModal").modal("show"); }); $("#myModal" ).on('show.bs.modal', function () { $('body').addClass('body-fixed'); }); $("#myModal").on('hide.bs. modal', function () { $('body').removeClass('body-fixed'); }); }); .body-fixed { 位置:固定;宽度:100%; } < !-- 模态 -->

F
FlavioEscobar

那些使用 position: fixed 和基于 scrollTop 的位置校正的解决方案非常有效,但有些人(包括我)遇到了另一个问题:键盘插入符号/光标在输入聚焦时不显示。

我观察到插入符号/光标仅在我们不要在正文上使用 position: fixed 时才有效。所以在尝试了几件事之后,我放弃了使用这种方法,并决定在 body 上使用 position: relative 并使用 scrollTop 来纠正 modal 的顶部位置

请参见下面的代码:

var iosScrollPosition = 0;

function isIOS() {
   // use any implementation to return true if device is iOS
}

function initModalFixIOS() {
    if (isIOS()) {
        // Bootstrap's fade animation does not work with this approach
        // iOS users won't benefit from animation but everything else should work
        jQuery('#myModal').removeClass('fade');
    }
}

function onShowModalFixIOS() {
    if (isIOS()) {
        iosScrollPosition = jQuery(window).scrollTop();
        jQuery('body').css({
            'position': 'relative', // body is now relative
            'top': 0
        });
        jQuery('#myModal').css({
            'position': 'absolute', // modal is now absolute
            'height': '100%',
            'top': iosScrollPosition // modal position correction
        });
        jQuery('html, body').css('overflow', 'hidden'); // prevent page scroll
    }
}

function onHideModalFixIOS() {
    // Restore everything
    if (isIOS()) {
        jQuery('body').css({
            'position': '',
            'top': ''
        });
        jQuery('html, body').scrollTop(iosScrollPosition);
        jQuery('html, body').css('overflow', '');
    }
}

jQuery(document).ready(function() {
    initModalFixIOS();
    jQuery('#myModal')
        .on('show.bs.modal', onShowModalFixIOS)
        .on('hide.bs.modal', onHideModalFixIOS);
});

A
Arman Charan

如前所述:将 bodystyle.position property 设置为 fixed 解决了 iOS cursor misplacement 问题。

然而,这种收益是以被强制滚动到页面顶部为代价的。

幸运的是,可以通过利用 HTMLElement.stylewindow.scrollTo() 来消除这个新的 UX 问题而无需太多开销。

基本要点是通过在 mounting 时操作 body 元素的 style.top 来抵消 scroll to top。这是使用 ygap 变量捕获的 YOffset 值完成的。

从那里只需将 body's style.top 重置为 0 并在 dismounting 时使用 window.scrollTo(0, ygap) 重新构建用户视图。

请参阅下面的实际示例。

// Global Variables (Manage Globally In Scope).
const body = document.querySelector('body') // Body.
let ygap = 0 // Y Offset.


// On Mount (Call When Mounting).
const onModalMount = () => {

  // Y Gap.
  ygap = window.pageYOffset || document.documentElement.scrollTop

  // Fix Body.
  body.style.position = 'fixed'

  // Apply Y Offset To Body Top.
  body.style.top = `${-ygap}px`

}


// On Dismount (Call When Dismounting).
const onModalDismount = () => {

  // Unfix Body.
  body.style.position = 'relative'

  // Reset Top Offset.
  body.style.top = '0'

  // Reset Scroll.
  window.scrollTo(0, ygap)

}

你有更详细的例子吗?我猜我会将 Mount 放在模态打开时调用的函数中,然后将 Dismount 放入函数中并在模态关闭时调用它。
啊,是的。我明白你的意思了。请参阅上面的修改后的解决方案。还;是的,目的是让您在 mountingdismounting 时调用那些 functions。谢谢。
M
Manuel Otto

如果有人正在寻找适用于 IOS >11.2 并且不需要任何额外 CSS 的 vanilla js 修复程序:

(function() {
    if (!/(iPhone|iPad|iPod).*(OS 11_[0-2]_[0-5])/.test(navigator.userAgent)) return

    document.addEventListener('focusin', function(e) {
        if (!e.target.tagName == 'INPUT' && !e.target.tagName != 'TEXTAREA') return
        var container = getFixedContainer(e.target)
        if (!container) return
        var org_styles = {};
        ['position', 'top', 'height'].forEach(function(key) {
            org_styles[key] = container.style[key]
        })
        toAbsolute(container)
        e.target.addEventListener('blur', function(v) {
            restoreStyles(container, org_styles)
            v.target.removeEventListener(v.type, arguments.callee)
        })
    })

    function toAbsolute(modal) {
        var rect = modal.getBoundingClientRect()
        modal.style.position = 'absolute'
        modal.style.top = (document.body.scrollTop + rect.y) + 'px'
        modal.style.height = (rect.height) + 'px'
    }

    function restoreStyles(modal, styles) {
        for (var key in styles) {
            modal.style[key] = styles[key]
        }
    }

    function getFixedContainer(elem) {
        for (; elem && elem !== document; elem = elem.parentNode) {
            if (window.getComputedStyle(elem).getPropertyValue('position') === 'fixed') return elem
        }
        return null
    }
})()

这是做什么的:

检查浏览器是否是 iOS 11.0.0 - 11.2.5 上的 Safari 监听页面上的任何 focusin 事件如果焦点元素是输入或文本区域并且包含在具有固定位置的元素中,则将容器位置更改为绝对位置关于 scrollTop 和容器的原始尺寸。在模糊时,将容器的位置恢复为固定。


A
Afzaal Khalid

这个解决方案对我有用,并且它在 iOS 上的所有浏览器上运行良好。

.safari-nav-force{
/* Allows content to fill the viewport and go beyond the bottom */
height: 100%;
overflow-y: scroll;
/* To smooth any scrolling behavior */
-webkit-overflow-scrolling: touch;
}

JavsScript

var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
$('.modal').on('shown.bs.modal', function () {
    if (iOS && $('.modal').hasClass('in')){
        $('html,body').addClass('safari-nav-force');
    }
});
$('.modal').on('hidden.bs.modal', function () {
    if (iOS && !$('.modal').hasClass('in')){
        $('html,body').removeClass('safari-nav-force');
    }
});

O
Oncleroger

您是否尝试过 viewport-fit=cover 元视口。

看看这个:https://ayogo.com/blog/ios11-viewport/


恐怕这对有问题的错误没有影响。
D
Dan

覆盖模态 css 并将其 positionfixed 更改为 absolute

.modal {
position: absolute !important;
}

在我的场景中不起作用。将固定更改为绝对可能会产生许多连锁反应
@SteveD - 要使其工作,您应该将模态附加到 。 应该有 - 位置:相对的。什么时候应该起作用:)
K
Karla

添加到#modal 位置:绝对它修复与位置相关的未来问题:已修复


您的答案是完全重复的。请确保不要发布重复的答案。