W przypadku safari w systemie iOS 11 kursor pola tekstowego do wprowadzania tekstu znajduje się poza polem tekstowym. Nie zrozumieliśmy, dlaczego ma ten problem. Jak widać, moje skupione pole tekstowe to wprowadzanie tekstu przez e-mail, ale mój kursor jest poza nim. Dzieje się tak tylko w przypadku Safari na iOS 11
html
ios
bootstrap-modal
mobile-safari
ios11
kekkeme
źródło
źródło
Odpowiedzi:
Naprawiłem problem, dodając
position:fixed
do ciała podczas otwierania modalu. Mam nadzieję, że to ci pomoże.źródło
width:100%
aby ograniczyć szerokość treści do szerokości urządzenia. W niektórych przypadkach, w zależności od istniejących znaczników, może to stanowić problem. Podoba mi się również rozwiązanie @gentleboy (poniżej), aby bez problemu nie karać innych przeglądarek, ponieważ ustawienie body na fixed powoduje, że ciało przewija się do góry, co jest nieco denerwujące.position:fixed
wniosek do treści wniosku. Zamiast tego zmieniłem toposition:absolute
nahtml
element i rozwiązałem mój problem. Dziękuję Jen!Osobiście
position: fixed
przewiń do góry automatycznie . Dość irytujące !Aby uniknąć karania innych urządzeń i wersji , stosuję tę poprawkę tylko do odpowiednich wersji iOS.
** WERSJA 1 - poprawka wszystkich modali **
W przypadku pliku 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"); } });
Dla CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
** WERSJA 2 - tylko wybrane modały **
Zmodyfikowałem funkcję, aby uruchamiała się tylko dla wybranych modali z klasą
.inputModal
Należy wpływać tylko na modały z danymi wejściowymi, aby uniknąć przewijania do góry.
W przypadku pliku 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); } }); } })(); });
Dla CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
Dla kodu HTML Dodaj klasę inputModal do pliku modal
<div class="modal fade inputModal" tabindex="-1" role="dialog"> ... </div>
Nota bene Funkcja javascript wywołuje się teraz automatycznie
** AKTUALIZACJA iOS 11.3 - Poprawiono błąd 😃🎉 **
Od iOS 11.3 błąd został poprawiony. Nie ma potrzeby testowania
OS 11_
wiOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
Ale uważaj, ponieważ iOS 11.2 jest nadal szeroko stosowany (stan na kwiecień 2018). Widzieć
stat 1
stat 2
źródło
iOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
ios11 = /OS 11_(\d{1,2})/.test(ua);
Ten problem wykracza poza Bootstrap i nie ogranicza się tylko do Safari. Jest to błąd pełnego wyświetlania w iOS 11, który występuje we wszystkich przeglądarkach. Powyższa poprawka nie rozwiązuje tego problemu we wszystkich przypadkach.
Błąd został szczegółowo zgłoszony tutaj:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
Podobno już zgłosili to Apple jako błąd.
źródło
Frustrujący błąd, dzięki za zidentyfikowanie go. W przeciwnym razie uderzałbym iPhonem lub głową o ścianę.
Najprostsza poprawka to (zmiana 1 linii kodu):
Po prostu dodaj następujący CSS do html lub do zewnętrznego pliku css.
<style type="text/css"> .modal-open { position: fixed; } </style>
Oto pełny przykład działania:
.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">×</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>
Zgłosiłem problem tutaj: https://github.com/twbs/bootstrap/issues/24059
źródło
Najłatwiejsze / najczystsze rozwiązanie:
body.modal-open { position: fixed; width: 100%; }
źródło
Ten problem nie jest już odtwarzalny po zaktualizowaniu urządzeń Apple do iOS 11.3
źródło
Dodaj
position: fixed;
dobody
kiedy modalna jest otwarta.$(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">×</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>
źródło
Te rozwiązania wykorzystujące
position: fixed
i oparte na korekcji pozycjiscrollTop
działają naprawdę dobrze, ale niektórzy ludzie (w tym ja) mają inny problem: kursor / kursor klawiatury nie wyświetla się, gdy dane wejściowe są skupione.Zauważyłem, że daszek / kursor działa tylko wtedy, gdy NIE używamy
position: fixed
na ciele. Więc po wypróbowaniu kilku rzeczy zrezygnowałem z tego podejścia i zdecydowałem się zamiast tego użyćposition: relative
onbody
i użyćscrollTop
do skorygowania górnej pozycji modalu .Zobacz kod poniżej:
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); });
źródło
Jak już wspomniano: ustawienie
style.position
property
ofbody
nafixed
rozwiązujeiOS cursor misplacement
problem.Jednak zysk ten odbywa się kosztem przymusowego przewinięcia do góry strony.
Na szczęście ten nowy
UX
problem można wyeliminować bez większych kosztów ogólnych, wykorzystując dźwignięHTMLElement.style
iwindow.scrollTo()
.Podstawowym Istotą jest, aby przeciwdziałać
scroll to top
poprzez manipulowaniebody
elementustyle.top
kiedymounting
. Odbywa się to za pomocąYOffset
wartości przechwyconej przezygap
zmienną.Stamtąd wystarczy zresetować
body's
style.top
do0
i przeformułować widok użytkownika za pomocąwindow.scrollTo(0, ygap)
kiedydismounting
.Poniżej znajduje się praktyczny przykład.
// 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) }
źródło
functions
kiedymounting
idismounting
. Dzięki.O ile ktoś szuka poprawki w vanilla js, która działa na IOS> 11.2 i nie wymaga żadnego dodatkowego CSS:
(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 } })()
Co to oznacza:
focusin
wydarzeń na stronieinput
lub atextarea
i jest zawarty w elemencie zfixed
pozycją, zmień położenie kontenera naabsolute
podczas uwzględnianiascrollTop
i oryginalnych wymiarów kontenerów.fixed
.źródło
To rozwiązanie działało dla mnie i działa dobrze we wszystkich przeglądarkach na 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'); } });
źródło
Czy spróbowałeś viewport-fit = cover dla meta rzutni.
Spójrz na to: https://ayogo.com/blog/ios11-viewport/
źródło
Zastąp modalne css i zmień jego wartość
position
zfixed
naabsolute
.modal { position: absolute !important; }
źródło
dodaj do pozycji #modalnej: bezwzględnie napraw przyszłe problemy związane z pozycją: naprawiono
źródło