Avec iOS 11 Safari, le curseur de la zone de texte d'entrée se trouve en dehors de la zone de texte d'entrée. Nous n'avons pas compris pourquoi il a ce problème. Comme vous pouvez le voir, ma zone de texte ciblée est une saisie de texte d'e-mail, mais mon curseur est en dehors de celle-ci. Cela ne se produit qu'avec iOS 11 Safari
html
ios
bootstrap-modal
mobile-safari
ios11
kekkeme
la source
la source
Réponses:
J'ai résolu le problème en ajoutant
position:fixed
au corps lors de l'ouverture d'un modal. J'espère que cela vous aidera.la source
width:100%
pour contraindre la largeur du corps à la largeur de l'appareil. Dans certains cas, en fonction du balisage existant, cela peut poser problème. J'aime aussi la solution de @gentleboy (ci-dessous) pour ne pas pénaliser les autres navigateurs sans problème, car lors de la définition du corps sur fixe fait défiler le corps vers le haut, ce qui est un peu gênant.position:fixed
postulé au corps de la demande. Au lieu de cela, je l'ai changéposition:absolute
sur l'html
élément et cela a résolu mon problème. Merci Jen!Personnellement,
position: fixed
faites défiler vers le haut automatiquement . Assez ennuyeux!Pour éviter de pénaliser d'autres appareils et versions, j'applique ce correctif uniquement aux versions appropriées d'iOS.
** VERSION 1 - Tous les modaux corrigent **
Pour le 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"); } });
Pour le CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
** VERSION 2 - Modaux sélectionnés uniquement **
J'ai modifié la fonction pour ne déclencher que pour les modaux sélectionnés avec une classe
.inputModal
Seuls les modaux avec des entrées doivent être impactés pour éviter le défilement vers le haut.
Pour le 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); } }); } })(); });
Pour le CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
Pour le HTML Ajoutez la classe inputModal au modal
<div class="modal fade inputModal" tabindex="-1" role="dialog"> ... </div>
Nota bene La fonction javascript est maintenant auto-appelante
** MISE À JOUR iOS 11.3 - Bug corrigé 😃🎉 **
Depuis iOS 11.3, le bogue a été corrigé. Il n'y a pas besoin de test
OS 11_
dansiOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
Mais soyez prudent car iOS 11.2 est toujours largement utilisé (en avril 2018). Voir
stat 1
stat 2
la source
iOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
ios11 = /OS 11_(\d{1,2})/.test(ua);
Ce problème va au-delà de Bootstrap et au-delà de Safari. Il s'agit d'un bogue d'affichage complet dans iOS 11 qui se produit dans tous les navigateurs. Le correctif ci-dessus ne résout pas ce problème dans tous les cas.
Le bug est rapporté en détail ici:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
Apparemment, ils l'ont déjà signalé à Apple comme un bogue.
la source
Bug frustrant, merci de l'avoir identifié. Sinon, je frapperais mon iPhone ou ma tête contre le mur.
La solution la plus simple est (1 ligne de changement de code):
Ajoutez simplement le CSS suivant au html ou à un fichier css externe.
<style type="text/css"> .modal-open { position: fixed; } </style>
Voici un exemple de travail complet:
.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>
J'ai soumis un problème ici: https://github.com/twbs/bootstrap/issues/24059
la source
Solution la plus simple / la plus propre:
body.modal-open { position: fixed; width: 100%; }
la source
Ce problème n'est plus reproductible après la mise à jour de vos appareils Apple vers iOS 11.3
la source
Ajouter
position: fixed;
àbody
lorsque modal est ouvert.$(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>
la source
Ces solutions utilisant
position: fixed
et la correction de position basée surscrollTop
fonctionnent très bien, mais certaines personnes (y compris moi) ont un autre problème: le curseur / curseur du clavier ne s'affiche pas lorsque les entrées sont ciblées.J'ai observé que le caret / curseur ne fonctionne que lorsque nous ne l' utilisons PAS
position: fixed
sur le corps. Donc , après avoir essayé plusieurs choses, j'ai renoncé à utiliser cette approche et a décidé d'utiliserposition: relative
surbody
et à l' utilisationscrollTop
de bonne position en haut de modal à la place.Voir le code ci-dessous:
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); });
la source
Comme mentionné précédemment: définir le
style.position
property
surbody
pourfixed
résout leiOS cursor misplacement
problème.Cependant, ce gain se fait au prix d'un défilement forcé vers le haut de la page.
Heureusement, ce nouveau
UX
problème peut être annulé sans trop de frais généraux en exploitantHTMLElement.style
etwindow.scrollTo()
.L'essentiel est de contrecarrer le
scroll to top
en manipulant le moment de l'body
élément . Ceci est fait en utilisant la valeur capturée par la variable.style.top
mounting
YOffset
ygap
À partir de là, il s'agit simplement de réinitialiser le
body's
style.top
vers0
et de recadrer la vue de l'utilisateur en utilisantwindow.scrollTo(0, ygap)
whendismounting
.Voir ci-dessous pour un exemple pratique.
// 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) }
la source
functions
quandmounting
etdismounting
. Merci.Incase quiconque cherche un correctif dans vanilla js qui fonctionne sur IOS> 11.2 et ne nécessite aucun CSS supplémentaire:
(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 } })()
Ce que cela fait est:
focusin
événements sur la pageinput
ou untextarea
et est contenu dans un élément avec lafixed
position, changer la position du conteneurabsolute
en ce qui concernescrollTop
et les conteneurs de dimensions d' origine.fixed
.la source
Cette solution a fonctionné pour moi et fonctionne bien sur tous les navigateurs sur 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'); } });
la source
Avez-vous essayé viewport-fit = cover pour la fenêtre méta.
Regardez ceci: https://ayogo.com/blog/ios11-viewport/
la source
Remplacer le css modal et changer son
position
defixed
àabsolute
.modal { position: absolute !important; }
la source
ajouter à la position #modal: absolu il corrige les futurs problèmes liés à la position: corrigé
la source