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

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

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

Страница ниже модальная в тот же момент автоматически прокручивается до 50% ее высоты. Такое поведение совершенно нежелательно, и я не знаю, как предотвратить эту функцию iOS по умолчанию.

Демо:

введите описание изображения здесь

Ответ 1

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

Мы сталкиваемся с аналогичной проблемой на работе. Как вы упомянули, смещение всегда составляет ~ 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');
    }
}

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

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

Итак, только когда вы сосредоточитесь на вводе, высоте и позиции будет определен, я уже закодировал это решение из вашего репо, я пришлю вам запрос на вытягивание. Я также добавил browserSync в настройку gulp. Поэтому теперь будет легко протестировать любое устройство.

Ура!

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, работает как прелесть для меня]

Ответ 5

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

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

body {
    overflow: hidden !important;
}

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

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

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

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

Во-вторых, мы должны добавить id к нашему модальному, <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;
}

И вот мы идем.

Ответ 6

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

position: fixed;
width: 100%;