Bei einer iOS 11-Safari befindet sich der Cursor für die Eingabe-Textbox außerhalb der Eingabe-Textbox. Wir haben nicht verstanden, warum es dieses Problem hat. Wie Sie sehen können, ist mein fokussiertes Textfeld die E-Mail-Texteingabe, aber der Cursor befindet sich außerhalb. Dies ist nur bei iOS 11 Safari der Fall
Ich habe das Problem behoben, indem ich beim Öffnen eines Modals position:fixed
zum Körper hinzugefügt habe . Ich hoffe, das hilft Ihnen.
Persönlich, position: fixed
scrollen automatisch nach oben. Ziemlich nervig !
Um zu vermeiden, dass andere Geräte und Versionen benachteiligt werden, wende ich diesen Fix nur auf die entsprechenden Versionen von iOS an.
Für das 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");
}
});
Für das CSS
/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
Ich habe die Funktion so geändert, dass sie nur für ausgewählte Modale mit der Klasse .inputModal
ausgelöst wird.
Nur die Modals mit Eingaben sollten betroffen sein, um das Scrollen nach oben zu vermeiden.
Für das 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);
}
});
}
})();
});
Für das CSS
/* Apply CSS to iOS affected versions only */
body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
Für HTML Fügen Sie dem Modal die Klasse inputModal hinzu
<div class="modal fade inputModal" tabindex="-1" role="dialog">
...
</div>
Nota bene Die Javascript-Funktion ruft jetzt selbst auf
Seit iOS 11.3 wurde der Fehler behoben. Es ist nicht notwendig, in iOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
auf OS 11_
zu testen.
Aber seien Sie vorsichtig, da iOS 11.2 immer noch weit verbreitet ist (Stand April 2018). Sehen
Dieses Problem geht über Bootstrap hinaus und über Safari hinaus. Es ist ein vollständiger Anzeigefehler in iOS 11, der in allen Browsern auftritt. Das obige Update behebt dieses Problem nicht in allen Fällen.
Der Fehler wird hier detailliert beschrieben:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
Angeblich haben sie Apple bereits als Fehler gemeldet.
Frustrierender Fehler, danke, dass Sie ihn identifiziert haben. Ansonsten würde ich mein iPhone oder meinen Kopf gegen die Wand schlagen.
Die einfachste Lösung ist (1 Zeile Codeänderung):
Fügen Sie der HTML-Datei oder einer externen CSS-Datei einfach das folgende CSS hinzu.
<style type="text/css">
.modal-open { position: fixed; }
</style>
Hier ist ein vollständiges Arbeitsbeispiel:
.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>
Ich habe hier ein Problem eingereicht: https://github.com/twbs/bootstrap/issues/24059
Einfachste/sauberste Lösung:
body.modal-open { position: fixed; width: 100%; }
Dieses Problem ist nach der Aktualisierung Ihrer Apple-Geräte auf .__ nicht mehr reproduzierbar. iOS 11.3
Fügen Sie position: fixed;
zu body
hinzu, wenn Modal geöffnet ist.
$(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>
Diese Lösungen, die position: fixed
und Positionskorrektur basierend auf scrollTop
verwenden, funktionieren sehr gut, aber einige Leute (einschließlich mir) haben ein anderes Problem: Der Tastaturcursor/Cursor erscheint nicht, wenn die Eingaben fokussiert sind.
Ich habe beobachtet, dass Caret/Cursor nur funktioniert, wenn DON'Tposition: fixed
für den Körper verwendet. Nachdem ich einige Dinge ausprobiert hatte, gab ich diesen Ansatz auf und entschied mich dazu, position: relative
für body
zu verwenden, und scrollTop
anstelle von modals oberer Position zu verwenden.
Siehe Code unten:
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);
});
Wie bereits erwähnt: Wenn Sie style.position
property
von body
auf fixed
setzen, wird das iOS cursor misplacement
-Problem gelöst.
Dieser Gewinn ist jedoch mit dem Preis verbunden, der zwangsweise an den Anfang der Seite verschoben wird.
Glücklicherweise kann dieses neue UX
-Problem ohne viel Aufwand durch das Verwenden von HTMLElement.style
und window.scrollTo()
negiert werden.
Das grundlegende Element besteht darin, dem scroll to top
entgegenzuwirken, indem der style.top
des body
-Elements bearbeitet wird, wenn mounting
. Dazu wird der von der Variablen YOffset
erfasste Wert ygap
verwendet.
Von dort aus geht es einfach darum, den body's
style.top
auf 0
zurückzusetzen und die Ansicht des Benutzers mit window.scrollTo(0, ygap)
umzustellen, wenn dismounting
.
Unten finden Sie ein praktisches Beispiel.
// 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)
}