Ио 11 сафари Bootstrap модальные текстовое поле за пределами курсора
в iOS 11 safari курсор текстового поля ввода находится за пределами текстового поля ввода. Мы не поняли, почему у него возникла эта проблема. Как вы можете видеть, мое сфокусированное текстовое поле-это ввод текста электронной почты, но мой курсор находится за его пределами. Это происходит только с iOS 11 Safari
16 ответов:
я исправил проблему путем добавления
position:fixed
к телу при открытии модального. Надеюсь, это поможет вам.
лично
position: fixed
прокрутка вверх автоматически. Очень раздражает !чтобы избежать наказания других устройств и версий я применяю это исправление только к соответствующим версиям iOS.
**Версия 1-все модалы исправить**
для 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"); } });
для CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
**версия 2-выбранные модалы только**
Я изменил функцию, чтобы стрелять только для выбранных модалов с классом
.inputModal
только модалы с входами должны быть затронуты, чтобы избежать прокрутки вверх.
для 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); } }); } })(); });
для CSS
/* Apply CSS to iOS affected versions only */ body.iosBugFixCaret.modal-open { position: fixed; width: 100%; }
для HTML Добавьте класс inputModal на режимное
<div class="modal fade inputModal" tabindex="-1" role="dialog"> ... </div>
Nota bene Этот функция JavaScript-это сейчас само-вызов
**обновление iOS 11.3 - Исправлена ошибка **
начиная с iOS 11.3, ошибка была исправлена. Там нет необходимости проверять на
OS 11_
наiOS11 = /OS 11_0|OS 11_1|OS 11_2/.test(ua);
но будьте осторожны поскольку iOS 11.2 по-прежнему широко используется (по состоянию на апрель 2018 года). Смотрите
эта проблема выходит за рамки Bootstrap, а не только Safari. Это ошибка полного отображения в iOS 11, которая возникает во всех браузерах. Исправление выше не устраняет эту проблему во всех случаях.
об ошибке подробно сообщается здесь:
https://medium.com/@eirik.luka/how-to-fix-the-ios-11-input-element-in-fixed-modals-bug-aaf66c7ba3f8
предположительно они уже сообщили об этом Apple как об ошибке.
разочарование ошибка, спасибо за идентификацию его. В противном случае, я бы стучал своим iphone или головой о стену.
самое простое исправление (1 строка изменения кода):
просто добавьте следующий CSS в html или во внешний файл css.
<style type="text/css"> .modal-open { position: fixed; } </style>
вот полный рабочий пример:
.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>
Я представил вопрос здесь: https://github.com/twbs/bootstrap/issues/24059
добавить
position: fixed;
доbody
когда модальный открыт.$(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>
эти решения с помощью
position: fixed
и коррекция положения на основеscrollTop
работать очень хорошо, но некоторые люди (включая меня) получили еще одну проблему: клавиатура каретка/курсор не показывает, когда входы сосредоточены.я заметил, что курсор/курсор работает только тогда, когда мы НЕ использовать
position: fixed
на теле. Поэтому, попробовав несколько вещей, я отказался от использования этого подхода и решил использоватьposition: relative
onbody
и использоватьscrollTop
исправить верхнее положение модала вместо.посмотреть код ниже:
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); });
как уже упоминалось ранее: установка
style.position
property
наbody
доfixed
разрешаетiOS cursor misplacement
вопрос.однако это увеличение происходит за счет принудительной прокрутки в верхней части страницы.
к счастью, это новое
UX
проблема может быть сведена на нет без особых накладных расходов за счет использованияHTMLElement.style
иwindow.scrollTo()
.основная суть заключается в противодействии
scroll to top
, управляяbody
элементstyle.top
, когдаmounting
. Это делается с помощьюYOffset
значение, захваченноеygap
переменной.оттуда это просто вопрос сброса
body's
style.top
до0
и рефрейминг представления пользователя с помощьюwindow.scrollTo(0, ygap)
, когдаdismounting
.см. ниже для практического примера.
// 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) }
если кто-то ищет исправление в vanilla js, которое работает на IOS >11.2 и не требует никаких дополнительных 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 } })()
это:
- проверьте, если браузер Safari на iOS 11.0.0-11.2.5
- слушайте любой
focusin
событий на странице- если сфокусированный элемент
input
илиtextarea
и содержится в элементе сfixed
положение, измените положение контейнера наabsolute
в то время как относительноscrollTop
и размеры контейнеров первоначальные.- при размытии восстановите положение контейнера до
fixed
.
это решение работает для меня и хорошо работает во всех браузерах на 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'); } });
вы попробуйте viewport-fit=cover для мета просмотра.
посмотрите на это:https://ayogo.com/blog/ios11-viewport/
переопределить модальный css и изменить его
position
Сfixed
доabsolute
.modal { position: absolute !important; }
проблема, как многие люди описали, заключается в следующем:
position:fixed
теперь, если вы откроете модальный, вы будете бросил в заголовок страницы... Чтобы избежать этого, я использую это решение (близко к @Will 's).
сначала я удостоверяюсь, что устройство iOS:
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
если устройство iOS-добавьте класс iOS-устройства в тело:
if (iOS) { $('body').addClass('iOS-device'); }
сделать переменную, чтобы удерживать позицию прокрутки:
var scrollPosition;
теперь обнаружить показать.БС.модальные события и установили iOS-устройства высшего свойства к негативным scrollPosition:
$('.modal').on('show.bs.modal', function() { scrollPosition = $(window).scrollTop(); $('.iOS-device').css('top', -scrollPosition); });
затем обнаружьтеhide.bs.modal событие, удалите класс modal-open, сбросьте верхнее значение iOS-устройства и прокрутите документ до точки, где он был до открытия modal:
$('.modal').on('hide.bs.modal', function() { $('.iOS-device').removeClass('modal-open'); $('.iOS-device').css('top', 0); $(document).scrollTop(scrollPosition); });
и полный код:
( function() { var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; if (iOS) { $('body').addClass('iOS-device'); } var scrollPosition; $('.modal').on('show.bs.modal', function() { scrollPosition = $(window).scrollTop(); $('.iOS-device').css('top', -scrollPosition); }); $('.modal').on('hide.bs.modal', function() { $('.iOS-device').removeClass('modal-open'); $('.iOS-device').css('top', 0); $(document).scrollTop(scrollPosition); }); })();
CSS:
body.modal-open.iOS-device { position: fixed; width: 100%; }
для такого рода проблемы мы нашли следующие 3 решения
1) измените контейнер с
position: fixed;
доposition: absolute;
. Недостатком этого является то, что пользователь может легко прокрутить от модального, что мы хотели бы занять окно недвижимости в первую очередь.2) Вы можете утверждать, что модалы не работают также и на меньших экранах, и лучшим обходным путем было бы вообще не использовать модалы, но это было бы довольно большим перепишите в нашем случае, и мы должны были получить исправление как можно скорее.
3) то, что мы нашли лучшим решением в нашем случае, чтобы сохранить модальный фиксированный, но растянуть его до краев окна, скрывая остальную часть содержимого в теле с
display: none;
. Это устранит проблему высоты тела, превышающей видовой экран, и не будет прокрутки фона при фокусировке на входе.узнать подробнее здесь
вышеупомянутая ссылка вы получите статус ошибки, т. е. она разрешена со стороны iPhone или нет