Con iOS 11 safari, el cursor del cuadro de texto de entrada está fuera del cuadro de texto de entrada. No entendimos por qué tiene este problema. Como puede ver, mi cuadro de texto enfocado es la entrada de texto de correo electrónico, pero mi cursor está fuera de él. Esto solo sucede con iOS 11 Safari
html
ios
bootstrap-modal
mobile-safari
ios11
kekkeme
fuente
fuente
Respuestas:
Solucioné el problema agregando
position:fixed
al cuerpo al abrir un modal. Espero que esto te ayudará.fuente
width:100%
para restringir el ancho del cuerpo al ancho del dispositivo. En algunos casos, dependiendo del marcado existente, eso podría ser un problema. También me gusta la solución de @gentleboy (abajo) para no penalizar a otros navegadores sin el problema, porque al configurar el cuerpo como fijo hace que el cuerpo se desplace hacia arriba, lo cual es algo molesto.position:fixed
solicitado al cuerpo de la aplicación. En cambio, lo cambié aposition:absolute
en elhtml
elemento y solucionó mi problema. ¡Gracias Jen!Personalmente,
position: fixed
desplácese hacia arriba automáticamente . Bastante molesto !Para evitar penalizar a otros dispositivos y versiones , aplico esta solución solo a las versiones apropiadas de iOS.
** VERSIÓN 1 - Se corrigen todos los modales **
Para 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"); } });
Para el CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
** VERSIÓN 2 - Solo modales seleccionados **
Modifiqué la función para que se active solo para modales seleccionados con una clase
.inputModal
Solo los modales con entradas deben verse afectados para evitar el desplazamiento hacia la parte superior.
Para 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); } }); } })(); });
Para el CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
Para el HTML, agregue la clase inputModal al modal
<div class="modal fade inputModal" tabindex="-1" role="dialog"> ... </div>
Nota bene La función javascript ahora se invoca automáticamente
** ACTUALIZAR iOS 11.3 - Error corregido 😃🎉 **
A partir de iOS 11.3, se corrigió el error. No es necesario realizar la prueba
OS 11_
eniOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
Pero tenga cuidado, ya que iOS 11.2 todavía se usa ampliamente (a partir de abril de 2018). Ver
estadística 1
estadística 2
fuente
iOS11 = /OS 11_(\d{1,2})(_{0,1})(\d{1,2})/.test(us);
ios11 = /OS 11_(\d{1,2})/.test(ua);
Este problema va más allá de Bootstrap y más allá de Safari. Es un error de visualización completo en iOS 11 que ocurre en todos los navegadores. La solución anterior no soluciona este problema en todos los casos.
El error se informa en detalle aquí:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
Supuestamente ya lo informaron a Apple como un error.
fuente
Error frustrante, gracias por identificarlo. De lo contrario, estaría golpeando mi iphone o mi cabeza contra la pared.
La solución más simple es (1 línea de cambio de código):
Simplemente agregue el siguiente CSS al html o a un archivo css externo.
<style type="text/css"> .modal-open { position: fixed; } </style>
Aquí hay un ejemplo de trabajo completo:
.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>
Envié un problema aquí: https://github.com/twbs/bootstrap/issues/24059
fuente
La solución más fácil / limpia:
body.modal-open { position: fixed; width: 100%; }
fuente
Este problema ya no se puede reproducir después de actualizar sus dispositivos Apple a iOS 11.3
fuente
Agregar
position: fixed;
abody
cuando modal esté abierto.$(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>
fuente
Esas soluciones que usan una
position: fixed
corrección de posición basada enscrollTop
funcionan muy bien, pero algunas personas (incluido yo) tienen otro problema: el cursor / cursor del teclado no se muestra cuando las entradas están enfocadas.Observé que el cursor de intercalación funciona solo cuando NO lo usamos
position: fixed
en el cuerpo. Así que después de probar varias cosas, me di por vencido en el uso de este enfoque y se decantó porposition: relative
elbody
usoscrollTop
de la correcta posición de la parte superior de modal en su lugar.Ver código a continuación:
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); });
fuente
Como se mencionó anteriormente: configurar el
style.position
property
debody
parafixed
resuelve eliOS cursor misplacement
problema.Sin embargo, esta ganancia tiene el costo de ser desplazado a la fuerza a la parte superior de la página.
Afortunadamente, este nuevo
UX
problema se puede solucionar sin demasiados gastos generales al aprovecharHTMLElement.style
ywindow.scrollTo()
.La esencia básica es contrarrestar el
scroll to top
manipulando el cuándobody
del elemento . Esto se hace utilizando el valor capturado por la variable.style.top
mounting
YOffset
ygap
Desde allí es simplemente una cuestión de reajustar el
body's
style.top
que0
y reformular la visión del usuario usandowindow.scrollTo(0, ygap)
cuandodismounting
.Vea a continuación un ejemplo práctico.
// 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) }
fuente
functions
cuandomounting
ydismounting
. Gracias.En caso de que alguien esté buscando una solución en vanilla js que funcione en IOS> 11.2 y no requiera ningún CSS adicional:
(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 } })()
Lo que hace esto es:
focusin
evento en la páginainput
o untextarea
y está contenido en un elemento confixed
posición, cambie la posición del contenedor aabsolute
mientras mirascrollTop
y las dimensiones originales del contenedor.fixed
.fuente
Esta solución funcionó para mí y funciona bien en todos los navegadores en 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'); } });
fuente
¿Has probado viewport-fit = cover para la meta viewport?
Mira esto: https://ayogo.com/blog/ios11-viewport/
fuente
Anular CSS modal y cambiar su
position
defixed
aabsolute
.modal { position: absolute !important; }
fuente
agregar a la posición #modal: absoluta, solucionar problemas futuros relacionados con la posición: arreglado
fuente