Vùng văn bản phương thức bootstrap của Safari iOS 11 bên ngoài con trỏ


85

Với iOS 11 safari, con trỏ hộp văn bản đầu vào nằm ngoài hộp văn bản đầu vào. Chúng tôi không hiểu tại sao nó lại gặp sự cố này. Như bạn có thể thấy hộp văn bản tập trung của tôi là kiểu nhập văn bản email nhưng con trỏ của tôi ở bên ngoài nó. Điều này chỉ xảy ra với iOS 11 Safari

Vấn đề


1
Đây là một lỗi với Safari. Apple đã sửa lỗi nội bộ nhưng bản sửa lỗi vẫn chưa có trong bản phát hành iOS công khai (hoặc thậm chí là phiên bản beta). bug.webkit.org/show_bug.cgi?id=176896
Beetle

Câu trả lời:


69

Tôi đã khắc phục sự cố bằng cách thêm position:fixedvào nội dung khi mở một phương thức. Hy vọng điều này sẽ giúp bạn.


6
Lưu ý cho mỗi câu trả lời bên dưới - Bootstrap thêm .modal-open vào body khi phương thức được mở, vì vậy bạn chỉ cần thêm vị trí: cố định vào lớp đó.
timmyc

1
Bạn cũng có thể cần thêm width:100%để hạn chế chiều rộng nội dung với chiều rộng thiết bị. Trong một số trường hợp, tùy thuộc vào đánh dấu hiện có, đó có thể là một vấn đề. Tôi cũng thích giải pháp của @g Bentleyboy (bên dưới) để không phạt các trình duyệt khác mà không gặp sự cố, bởi vì khi đặt body thành fixed sẽ khiến phần thân cuộn lên trên cùng, điều này hơi khó chịu.
Redtopia

Thật kỳ lạ, tôi đã gặp sự cố này với một bản xây dựng ứng dụng với meteor-cordova. Có vẻ như bất kỳ thiết bị iOS nào chạy v11 + đều gặp sự cố này. Trong trường hợp của tôi, tôi đã position:fixedáp dụng cho phần nội dung của ứng dụng. Thay vào đó, tôi đã thay đổi nó thành position:absolutetrên htmlphần tử và nó đã khắc phục sự cố của tôi. Cảm ơn Jen!
Adam Ross Bowers

1
Đây có thể là sự kết thúc của các hình thức phương thức đối với chúng tôi. Ngay cả khi Apple khắc phục sự cố, người dùng sẽ phải cập nhật thiết bị của họ để xem biểu mẫu hoạt động. Không có một cách phổ quát dễ dàng hơn để khắc phục điều này? Điều gì về một điền nhiều?
Reado

1
bạn đã cứu mạng tôi <3
Cristian B.

42

Cá nhân, position: fixed tự động cuộn lên đầu trang . Khá khó chịu !

Để tránh phạt các thiết bị và phiên bản khác, tôi chỉ áp dụng bản sửa lỗi này cho các phiên bản iOS thích hợp.


** PHIÊN BẢN 1 - Đã sửa tất cả các chế độ **

Đối với 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");

    }

});

Đối với CSS

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

** PHIÊN BẢN 2 - Chỉ các phương thức đã chọn **

Tôi đã sửa đổi chức năng để chỉ kích hoạt cho các phương thức đã chọn với một lớp .inputModal

Chỉ các phương thức có đầu vào mới được tác động để tránh cuộn lên đầu.

Đối với 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);
                }
            });

        }
    })();
});

Đối với CSS

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

Đối với HTML Thêm class inputModal vào phương thức

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

Nota Bene Chức năng javascript hiện đang tự gọi


** CẬP NHẬT iOS 11.3 - Đã sửa lỗi 😃🎉 **

Kể từ iOS 11.3, lỗi đã được sửa chữa. Không cần phải kiểm tra OS 11_trongiOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);

Nhưng hãy cẩn thận vì iOS 11.2 vẫn được sử dụng rộng rãi (tính đến tháng 4 năm 2018). Xem

stat 1

stat 2


2
Lời khuyên tốt. Tôi không có vấn đề này nhưng tôi đoán đây có thể là câu trả lời toàn cầu. Tôi sẽ thêm nó sau khi uống xong các loại bia của mình
micaball

3
@g Bentley Tại sao không sử dụng REGEX để tìm bất kỳ hệ điều hành 11 nào? Vì vậy, theo cách đó bạn sẽ không phải cập nhật từng bản cập nhật OS 11 cho mã của mình? một cái gì đó như thế nàyiOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
T. Evans

1
@RonakK có vẻ như nó vẫn còn hiện diện trong phiên bản beta 11,2 và 11,3 theo bugs.webkit.org
micaball

2
@ T.Evans rằng regex không hoạt động. Một regex đúng có thể là một cái gì đó như thế này:ios11 = /OS 11_(\d{1,2})/.test(ua);
Abraham

2
Vị trí cố định sẽ vẫn đưa tài liệu / nội dung cuộn lên trên cùng. Tôi khuyên bạn nên lấy vị trí scrollTop hiện tại trên phương thức mở và giá trị readd scrollTop sau khi phương thức đóng. Thích điều này jsfiddle.net/im4aLL/hmvget9x/1
HADI

15

Vấn đề này vượt ra ngoài Bootstrap và ngoài Safari. Đây là một lỗi hiển thị đầy đủ trong iOS 11 xảy ra trên tất cả các trình duyệt. Bản sửa lỗi ở trên không khắc phục được sự cố này trong mọi trường hợp.

Lỗi được báo cáo chi tiết tại đây:

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

Được cho là họ đã báo cáo lỗi cho Apple.


Đây dường như là vấn đề đối với tôi, hoạt động tốt trước khi cập nhật lên IOS 11. Người dùng Android không gặp vấn đề.
hackingchemist

11

Lỗi đáng thất vọng, cảm ơn bạn đã xác định nó. Nếu không, tôi sẽ đập chiếc iphone của mình hoặc đầu vào tường.

Cách khắc phục đơn giản nhất là (1 dòng thay đổi mã):

Chỉ cần thêm CSS sau vào html hoặc vào tệp css bên ngoài.

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

Đây là một ví dụ hoạt động đầy đủ:

.modal-open { position: fixed; }
<link href="https://getbootstrap.com/docs/3.3/dist/css/bootstrap.min.css" rel="stylesheet">

<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@mdo">Open modal for @mdo</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@fat">Open modal for @fat</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="@getbootstrap">Open modal for @getbootstrap</button>
...more buttons...

<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="exampleModalLabel">New message</h4>
      </div>
      <div class="modal-body">
        <form>
          <div class="form-group">
            <label for="recipient-name" class="control-label">Recipient:</label>
            <input type="text" class="form-control" id="recipient-name">
          </div>
          <div class="form-group">
            <label for="message-text" class="control-label">Message:</label>
            <textarea class="form-control" id="message-text"></textarea>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Send message</button>
      </div>
    </div>
  </div>
</div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://getbootstrap.com/docs/3.3/dist/js/bootstrap.min.js"></script>

Tôi đã gửi sự cố ở đây: https://github.com/twbs/bootstrap/issues/24059


Đây nên là câu trả lời. Bootstrap thêm lớp mở phương thức vào phần thân khi phương thức được hiển thị. Bạn chỉ cần nhắm mục tiêu lớp đó.
lfkwtz

1
Tôi đã giải quyết vấn đề này trong một thời gian. Giải pháp này không phù hợp với tôi khi thêm vị trí cố định sẽ cuộn trang trở lại đầu trang. Vì vậy, khi người dùng đóng phương thức, họ sẽ ở một vị trí cuộn khác. Điều này dẫn đến trải nghiệm người dùng tồi tệ
Nearpoint 14/10/17

Bản sửa lỗi này đã phù hợp với tôi khi sử dụng Chrome trên thiết bị di động. Lúc đầu hơi bối rối vì .modal-open không xuất hiện trong html phương thức, nhưng dù sao thì tôi cũng đã thêm nó vào dưới dạng CSS trong tiêu đề của tôi và nó đã hoạt động.
David

4

Giải pháp dễ nhất / sạch nhất:

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

1
Đây là giải pháp dễ dàng nhất và nó hoạt động, nhưng vấn đề duy nhất là con trỏ biến mất hoàn toàn. Nó không tệ như tình trạng ban đầu, nhưng có một vấn đề về khả năng sử dụng.
tmo256,

Weird, tôi đã không trải qua một con trỏ biến mất
lfkwtz

1
Tôi cũng đã trải nghiệm con trỏ biến mất, bất kỳ suy nghĩ nào tại sao điều đó có thể xảy ra?
Alex Burgos

4
Vâng, tôi cũng thấy một con trỏ biến mất chỉ cho sự kiện tiêu điểm đầu tiên. Các tiêu điểm đầu vào tiếp theo có con trỏ xuất hiện. Rất lạ. Điều này chỉ xảy ra trong Safari trên iOS.
Devin Walker

@DevinWalker các bạn đã bao giờ giải quyết vấn đề con trỏ biến mất chưa?
cấp

3

Sự cố này không còn tái tạo sau khi cập nhật thiết bị apple của bạn lên iOS 11.3


Ý bạn là gì, Apple đã sửa nó?
Starscream

1
@Starscream vâng nó đã được apple sửa lỗi với phiên bản phần mềm này (iOS 11.3)
Eashan

2

Thêm position: fixed;vào bodykhi phương thức đang mở.

$(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 {
    position: fixed;
    width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>

<button type="button" class="btn btn-info btn-lg" id="myBtn">Open Modal</button>

<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
	<div class="modal-dialog">
		<div class="modal-content">
			<div class="modal-header">
				<button type="button" class="close" data-dismiss="modal">&times;</button>
				<h4 class="modal-title">Form</h4>
			</div>
			<div class="modal-body">
				<div class="form-group">
					<label class="control-label">Input #1</label>
					<input type="text" class="form-control">
				</div>
				<div class="form-group">
					<label class="control-label">Input #2</label>
					<input type="text" class="form-control">
				</div>
				<div class="form-group">
					<label class="control-label">Input #3</label>
					<input type="text" class="form-control">
				</div>
				<div class="form-group">
					<label class="control-label">Input #4</label>
					<input type="text" class="form-control">
				</div>
			</div>
			<div class="modal-footer">
				<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
			</div>
		</div>
	</div>
</div>


1
Tương tự như các giải pháp khác trên chủ đề này, sau khi phương thức đóng lại - bạn sẽ trở lại đầu một lần nữa. Ví dụ: người dùng cuộn qua lưới các mục, khởi chạy chi tiết trong một phương thức .. và với bản sửa lỗi này, khi họ đóng phương thức .. họ lại ở trên cùng của lưới các mục một lần nữa và phải cuộn lại
bkwdesign

2
ngày 7 iPhone plus của tôi, sửa chữa điều này gây ra con trỏ của tôi biến mất hoàn toàn
bkwdesign

1

Những giải pháp sử dụng position: fixedvà sửa vị trí dựa trên scrollTophoạt động thực sự tốt, nhưng một số người (bao gồm cả tôi) gặp phải vấn đề khác: dấu mũ bàn phím / con trỏ không hiển thị khi đầu vào được lấy nét.

Tôi quan sát thấy rằng dấu mũ / con trỏ chỉ hoạt động khi chúng tôi KHÔNG sử dụng position: fixedtrên cơ thể. Vì vậy, sau khi thử một vài điều, tôi đã từ bỏ việc sử dụng phương pháp này và quyết định sử dụng position: relativetrên bodyvà sử dụng scrollTopđể đúng vị trí hàng đầu phương thức của thay thế.

Xem mã bên dưới:

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

0

Như đã đề cập trước đây: thiết lập style.position propertycủa bodyđể fixedgiải quyết iOS cursor misplacementvấn đề.

Tuy nhiên, lợi nhuận này đi kèm với cái giá phải trả là bị buộc phải cuộn lên đầu trang.

May mắn thay, UXvấn đề mới này có thể được phủ nhận mà không tốn kém nhiều chi phí bằng cách tận dụng HTMLElement.stylewindow.scrollTo().

Ý chính cơ bản là chống lại scroll to topbằng cách thao tác khi bodycủa phần tử . Điều này được thực hiện bằng cách sử dụng giá trị được bắt bởi biến.style.topmountingYOffsetygap

Từ đó nó chỉ đơn giản là vấn đề thiết lập lại body's style.topđể 0và sắp xếp lại quan điểm của người sử dụng sử dụng window.scrollTo(0, ygap)khi dismounting.

Xem bên dưới để biết một ví dụ thực tế.

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

}

Bạn có một ví dụ chi tiết hơn cho điều này? Tôi đoán rằng tôi sẽ có Mount trong một hàm được gọi khi phương thức mở ra, sau đó đặt Dismount trong một hàm và gọi hàm đó khi phương thức đóng.
Neal Jones

Aahh vâng. Tôi hiểu ý bạn là gì. Vui lòng xem ở trên để biết giải pháp sửa đổi. Cũng thế; vâng, mục đích là để bạn gọi chúng functionskhi mountingdismounting. Cảm ơn.
Arman Charan

-1

Trong trường hợp bất kỳ ai đang tìm kiếm bản sửa lỗi trong vanilla js hoạt động trên IOS> 11.2 và không yêu cầu bất kỳ CSS bổ sung nào:

(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
    }
})()

Điều này làm là:

  1. Kiểm tra xem trình duyệt có phải là Safari trên iOS 11.0.0 - 11.2.5 hay không
  2. Nghe bất kỳ focusinsự kiện nào trên trang
  3. Nếu phần tử tập trung là một inputhoặc một textareavà được chứa trong một phần tử cófixed vị trí, hãy thay đổi vị trí vùng chứa thành absolutetrong khi liên quan đến scrollTopvà các kích thước ban đầu của vùng chứa.
  4. Khi làm mờ, hãy khôi phục vị trí của vùng chứa thành fixed.

-1

Giải pháp này phù hợp với tôi và nó hoạt động tốt trên tất cả các trình duyệt trên 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');
    }
});


-2

Ghi đè css phương thức và thay đổi nó positiontừ fixedthànhabsolute

.modal {
position: absolute !important;
}

1
Không hoạt động trong kịch bản của tôi. Thay đổi cố định thành tuyệt đối có thể có NHIỀU hiệu ứng
Steve D

@SteveD - để làm cho nó hoạt động, bạn nên thêm phương thức của mình vào <body>. Và <body> nên có - position: relative. Và khi nào nó sẽ hoạt động :)
Dan

-3

thêm vào vị trí #modal: tuyệt đối nó khắc phục các sự cố trong tương lai liên quan đến vị trí: fixed


Câu trả lời của bạn là một bản sao chính xác. Vui lòng đảm bảo không đăng các câu trả lời trùng lặp.
MechMK1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.