Подтвердить что ты не робот

Предотвращение отказов iOS без отключения прокрутки

Я пытаюсь реализовать решение для предотвращения эффекта отказов iOS в Safari для iOS, когда содержимое веб-страницы больше, чем область просмотра.

Страница, над которой я работаю, довольно специфична по своей структуре и очень похожа на эту страницу http://new.salt.ch/

  • Базовая структура основана на бутстрапе.
  • Он имеет фиксированную панель навигации вверху.
  • У него полноэкранное слайд-шоу.
  • У слайд-шоу есть наложение, которое прикреплено к нижней части области просмотра.
  • Существует элемент нижнего колонтитула, который загружается вне холста и отображается только при прокрутке содержимого.
  • Контент прокручивается за панелью навигации.
  • Содержимое состоит из заголовка, расположенного на 20 пикселей ниже панели навигации, и ряда кнопок, расположенных на 20 пикселей выше области просмотра.
  • При прокрутке все кнопки и заголовок перемещаются вверх по экрану для отображения нижнего колонтитула.

Проблема, с которой я столкнулся, такая же, как и проблема на странице http://new.salt.ch/ в том, что при прокрутке вверх вы получаете эффект отскока внизу экрана, который показывает фон и наложение.

Я пробовал различные решения, включая iNoBounce.js, Nonbounce.js и несколько других предложений, которые я нашел в SO.

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

4b9b3361

Ответ 1

Этот код должен остановить отскок, поскольку это тег HTML, который отскакивает

html {
    height  : 100%;
    overflow: hidden;
}
body {
    height  : 100%;
    overflow: auto;
}

Ответ 2

Если я правильно истолковываю ваш вопрос, у нас возникла одна и та же проблема в течение многих лет, когда мы разрабатывали кроссплатформенные мобильные веб-приложения, пытаясь заставить все различные проприетарные функции прокрутки работать правильно на каждом устройстве: Apple iOS, Google Android, Windows Телефон, ноутбук Chrome, ноутбук Safari, IE и ноутбук Edge.

jQuery Mobile продолжает пытаться исправить это в рамках своей платформы, но это слишком много, с постоянными обновлениями от каждого производителя устройств/производителя ОС.

Да, у нас есть решения для каждого отдельного мобильного устройства. И мы протестировали, но серьезно не рассматривали вопрос разработки платформ подкачки для каждого устройства, требующих от нас обнаружения каждого устройства и представления немного разных фреймворков для каждого устройства. Безумно плохая идея - в основном поддерживать не менее 3 и не более десятка различных версий вашего кода.

РЕШЕНИЕ: Нам больше всего повезло, просто поместив свой постоянный верхний и нижний колонтитулы поверх вашей структуры страницы. Вот простое решение с использованием встроенных стилей:

<html>
<head>
  <title>Fixed Header and Footer on All Mobile Web Apps</title>
  <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0" />
  <style>
    html, body { height:100%; width:100%; }
  </style>
</head>
<body>
<div style="position: fixed; height:100%; width:100%; top:0; left:0;">
  <div style="height:calc(100% - 1px); width:100%; margin-top: 60px; z-index: 1; overflow-y: scroll; -webkit-overflow-scrolling: touch;">
    [Body Content That Can Scroll if it extends beyond screen...]

  </div>
  <div style="position: absolute; top:0; left:0; width:100%; height: 60px; background:#dddddd; z-index:10;">
    [Header Content...]

  </div>
  <div style="position: absolute; bottom:0; left:0; width:100%; height: 40px; background:#cccccc; z-index:11;">
    [Footer Content...]

  </div>
</div>
</body>
</html>

Таким образом, Body может быть любым набором страниц jQuery Mobile. Фактически, теоретически, Body может быть практически любым контентом из любой среды.

Особое примечание, строка с высотой: calc (100% - 1px); имеет решающее значение для магии.

Казалось бы, бесконечные комбинации или перестановки в этом вопросе стали для нас на протяжении многих лет крестовым походом, пытаясь найти самое чистое, простое и универсально совместимое решение. Таким образом, после того, как мы посвятили смущающему количеству человеко-часов этой теме, это не только наше лучшее решение, но и ЕДИНСТВЕННЫЙ универсально совместимый подход, который мы обнаружили, который также позволяет вам придерживаться только единственного кода. Он был успешно протестирован на последних версиях iOS, Windows Phone, Android, ноутбука Chrome, ноутбука Safari, PhoneGap, ноутбука Firefox, IE 9-11 и Windows Edge.

TAGS: мобильное приложение, веб-приложение, фиксированный верхний колонтитул, постоянный нижний колонтитул, постоянный нижний колонтитул, постоянный нижний колонтитул, проблема с прокруткой, отскок прокрутки iOS, отскок Chrome, отскок прокрутки Android, проблема с прокруткой веб-набора, прокрутка с помощью сенсорного веб-прокрутки, проблема с сенсорной прокруткой iOS

Ответ 3

Я просмотрел несколько ответов по SO, и все выглядело мрачно, пока не наткнулся на этот код.

html {
  position: fixed;
  height: 100%;
  overflow: hidden;
}

body {
  width: 100vw;
  height: 100vh;
  overflow-y: scroll;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}

Объявления стиля для body могут быть помещены в любой элемент, который вы хотите иметь возможность прокручивать. Вы также можете изменить overflow-x и overflow-y по мере необходимости. Мне лично это нужно, чтобы НЕ прокручивать в стороны, поэтому я объявил это так.

Обновление 15 сентября 2017: Мне пришлось использовать это исправление для другого проекта, и я смог обойтись без этих объявлений position: fixed и height: 100%; в селекторе html. YMMV

Обновление от 12 апреля 2018 года (упомянуто в комментариях): если вы используете фиксированные элементы на странице, эти элементы могут иметь визуальную "дрожь" при прокрутке.

Ответ 5

Мне удалось решить большинство проблем с поддержкой overflow: auto и overflow: scroll на мобильном Safari:

  • не наведя вид прокрутки после касания в начале списка, затем перемещаясь вниз и затем вверх (в этом случае мобильный Safari запускает свое поведение по умолчанию для всей страницы)
  • поддержка фиксированного заголовка/панели действий сверху без уродливого перекрытия ее с помощью полосы прокрутки

window.addEventListener('DOMContentLoaded', function () {
                        
  var atTop = true;
  var atBottom = false;

  var body = document.getElementById('fixedBody');
  body.addEventListener('touchmove', function(event){
    event.preventDefault();
  });

  body.addEventListener('touchstart', function(event){
    event.preventDefault();
  });

  body.addEventListener('touchend', function(event){
    event.preventDefault();
  });

  var scrollingDiv = document.getElementById('scrollDiv');
  if (scrollingDiv.scrollHeight <= scrollingDiv.clientHeight) {
    atBottom = true;
  }

  scrollingDiv.addEventListener('scroll', function(event){
    
    if (event.target.scrollTop === 0) {
      atTop = true;
    } else {
      atTop = false;
    }
    
    if (event.target.scrollHeight - event.target.scrollTop === event.target.clientHeight) {
      atBottom = true;
    } else {
      atBottom = false;
    }
  });
  
  var lastY = 0;
  var topLock = false;
  var bottomLock = false;
  
  scrollingDiv.addEventListener('touchmove', function(event){
    event.stopPropagation();
    var currentY = event.touches[0].clientY;
    if (currentY > lastY) {
      // moved down
      if (atTop) {
        event.preventDefault();
        topLock = true;
      }

      if (bottomLock) {
        bottomLock = false;
        // TODO: Emulate finger remove and touch again here
      }
    } else if(currentY < lastY){
      // moved top
      if (atBottom) {
        event.preventDefault();
        bottomLock = true;
      }

      if (topLock) {
        topLock = false;
        // TODO: Emulate finger remove and touch again here
      }
    }
     
    lastY = currentY;
  });

  scrollingDiv.addEventListener('touchstart', function(event){
    lastY = event.touches[0].clientY;
    event.stopPropagation();
  });

  scrollingDiv.addEventListener('touchend', function(event){
    event.stopPropagation();
  });

});
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
</head>
<body id="fixedBody" style="overflow: hidden;">
  <div style="position: fixed; height: 64px; width:100%; top:0; left:0; background-color: green; z-index: 1;">
    Header
  </div>
  <div id="scrollDiv" style="position: absolute; width: 100%; top: 64px; bottom: 0px; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; background-color: white;">
    <div style="height: 150px; background-color: blue;">
      First
    </div>
    <div style="height: 150px; background-color: red;">
      Second
    </div>
    <div style="height: 150px; background-color: green;">
      Third
    </div>
    <div style="height: 150px; background-color: black;">
      Another
    </div>
  </div>
</body>
</html>

Ответ 6

Ни один из этих ответов не работает в 2019 году для iOS 13 для мобильных Safari.