iOS Safari / Chrome-нежелательная прокрутка при фокусировке ввода внутри модального

протестировано в Safari и Chrome-тот же результат, поэтому я думаю, что это проблема iOS.

Это происходит, только если есть вход внутри модального, и я нажимаю этот вход. В тот же момент, что вход получил фокус и родную клавиатуру iOS становятся видимыми.

страница ниже модальной в тот же момент автоматически прокручивается до 50% ее высоты. Это поведение совершенно нежелательно, и я понятия не имею, как предотвратить эту iOS по умолчанию "особенность."

демо:

enter image description here

6 ответов


просто добавив ответ здесь, если люди наткнутся на этот вопрос (а не ваш другой вопрос, который имеет отличную демонстрацию, чтобы проиллюстрировать эту проблему)

мы сталкиваемся с аналогичной проблемой на работе. Как вы упомянули, смещение всегда составляет ~50% высоты страницы, что происходит независимо от того, где находится ваше начальное смещение.

в прошлом, когда я наблюдал подобные "прыжки" с более ранними версиями iOS( хотя, гораздо менее драматичные прыжки), я обычно работали вокруг этого, применяя position: fixed (или relative) к body (позволяет overflow: hidden для правильной работы).

однако это имеет автоматическое последствие перехода пользователя обратно в верхнюю часть страницы, если они прокрутили вниз.

Итак, если вы открыты для решения этой проблемы с некоторыми JavaScript, вот исправление / хак, который я бросил вместе:

// Tapping into swal events
onOpen: function () {
  var offset = document.body.scrollTop;
  document.body.style.top = (offset * -1) + 'px';
  document.body.classList.add('modal--opened');
},
onClose: function () {
  var offset = parseInt(document.body.style.top, 10);
  document.body.classList.remove('modal--opened');
  document.body.scrollTop = (offset * -1);
}

и как выглядит CSS:

.modal--opened {
  position: fixed;
  left: 0;
  right: 0;
}

здесь вилка вашей демо-страницы (из вашего другого вопроса), чтобы проиллюстрировать:https://jpattishall.github.io/sweetalert2/ios-bug.html

и для тех, кто ищет более общее исправление, вы можете сделать что-то вроде следующего при открытии/закрытии модального:

function toggleModal() {
    var offset;
    if (document.body.classList.contains('modal--opened')) {
        offset = parseInt(document.body.style.top, 10);
        document.body.classList.remove('modal--opened');
        document.body.scrollTop = (offset * -1);
    } else {
        offset = document.body.scrollTop;
        document.body.style.top = (offset * -1) + 'px';
        document.body.classList.add('modal--opened');
    }
}

Edit: чтобы избежать "переключения / отключения" на рабочих столах, я бы предложил обнаружение функций / UA sniffing применить это только к мобильному safari.


поэтому я решил это и протестировал на своем Iphone 5, У меня нет Ipad для проверки. Я отключить overflow:hidden в моем решении вы можете добавить, если хотите отключить прокрутку все в одном для всех модалов. Решение состоит в том, чтобы добавить в основном свойство height и position как к html, так и к элементу body.

html, body {
   position:relative;
   /*overflow:hidden;*/
   height: 100%;
}

таким образом, только когда вы сосредоточитесь на входе, высоте и положении, я уже закодировал это решение из вашего РЕПО, я отправлю вам запрос на вытягивание. Я также добавил browsersync в в настройках залпом. Поэтому теперь его будет легко протестировать на любом устройстве.

Ура!

EDIT: другой способ, если выше решение не работает по какой-то причине. затем,

 /*
  * @summary touch handler; will remove touch ability
  * @author yeomann
  */
  function Touchyhandler(e) {
    e.preventDefault();
  }

и позже прагматично добавить и удалить сенсорный прослушиватель, как это

//to add
document.addEventListener('touchmove', Touchyhandler, false); 
//to remove   
document.removeEventListener('touchmove', Touchyhandler);

над решением js, протестированным на IOS 9.3.2, работает как шарм для меня]


чтобы остановить прокрутку страницы, как по оси x, так и по оси y, мы используем overflow: hidden; атрибут в css.

Итак, если мы применим это к телу,

body {
    overflow: hidden !important;
}

он должен работать правильно?

на самом деле, это на самом деле не работает, потому что вы только что отключили прокрутку x и y для всей страницы в течение всего времени.

чтобы обойти это, мы можем использовать TAD javascript для добавления класса в тело, когда модальный активен.

Сначала мы должны добавьте идентификатор к нашему телу,<body id="body"> это позволяет javascript распознавать тело.

во-вторых, мы должны добавить идентификатор к нашему модальному,<div id="modal">, также позволяя javascript распознавать модальные.

<script type="text/javascript">
    function modalActive() {
        if (document.getElementById("modal").classList.contains("active")) {
            document.getElementById("body").classList.add("modal-active");
        } else {
            getElementById("modal").classList.remove("active"));
            getElementById("body").classList.remove("modal-active"));           
        }
    }
</script>

для кнопки, которая запускает и закрывает модальный, мы должны добавить событие onclick,

<button onclick="modalActive()">Click Me!</button>

кроме того, мы должны добавить это в файл css.

body {
    overflow: initial !important;
}

body.modal-active {
    overflow: hidden !important;
}

и вот мы идем.


Я не уверен на 100%, но я могу представить следующее:

при появлении клавиатуры высота окна уменьшается, но значение scrollTop остается прежним, поэтому сайт переходит к этому значению. Вы можете добавить overflow:hidden до body когда модальный открыт. Это заблокирует прокрутку" за " модальным и, вероятно, решит вашу проблему.


Я также испытал эту проблему. Краткое объяснение заключается в том, что iOS Safari попытается автоматически прокрутить любой вход, на котором сосредоточен, и в этом конкретном случае сфокусированный элемент находится в фиксированном позиционированном элементе. Safari, похоже, борется с поиском элемента фиксированной позиции, когда он хочет центрировать элемент на экране, следовательно, прокрутка фона.

одним из возможных решений является добавление touchstart прослушиватель событий в поле ввода и вычислить текущий положение оверлея, измените положение на абсолютное и обновите верхнее / левое положение, чтобы поместить оверлея туда, где он был на экране при фиксированном положении, и, наконец, добавьте новый blur прослушиватель для сброса наложения обратно в фиксированное положение при выходе фокуса / размытия на входе. Это должно предотвратить прокрутку страницы. Я предлагаю использовать touchstart потому что он должен вызвать перед focus событие, при котором страница уже начнет прокрутку. Safari должен иметь возможность найдите и центрируйте абсолютное расположенное наложение, когда focus событие срабатывает.


Я пробовал несколько вещей, которые работали для модальных входов на html-странице. Самым простым решением, которое сработало для меня, было добавление следующих стилей в тег тела, когда модальный открыт на странице.

position: fixed;
width: 100%;