web-dev-qa-db-ja.com

iOS Safari / Chrome-モーダル内で入力をフォーカスする際の不要なスクロール

SafariとChromeでテスト済み-同じ結果です。iOSの問題だと思います。

これは、モーダル内に入力があり、その入力をタップした場合にのみ発生します。入力がフォーカスを取得し、ネイティブiOSキーボードが表示されるのと同じ瞬間に。

同じ瞬間にモーダル以下のページは、その高さの50%まで自動的にスクロールされます。この動作は完全に望ましくなく、このデフォルトのiOSの「機能」を防ぐ方法はわかりません。

デモ:

enter image description here

20
Limon Monte

人々がこの質問に出くわした場合に備えて、ここに答えを追加するだけです( この問題を説明する素晴らしいデモがある他の質問ではなく

職場でも同様の問題に直面しています。前述のように、オフセットは常にページの高さの約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スニッフィングをモバイルサファリのみに適用することをお勧めします。

10
Jack

X軸とy軸の両方でページのスクロールを停止するには、cssで_overflow: hidden;_属性を使用します。

これを体に適用すると、

_body {
    overflow: hidden !important;
}
_

正しく機能するはずですか?

実際、これは実際には機能しません。なぜなら、ページ全体のxスクロールとyスクロールをずっと無効にしているからです。

これを回避するために、モーダルがアクティブなときに、少し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;
}
_

そしてそこに行きます。

1
harryparkdotio

私もこの問題を経験しました。簡単な説明は、iOS Safariはフォーカスされている入力に自動スクロールしようとし、この特定の場合、フォーカスされた要素は固定された要素内にあるということです。 Safariは、要素を画面の中央に配置するために固定位置要素を見つけるのに苦労しているようです。したがって、背景のスクロールです。

可能な修正方法の1つは、touchstartイベントリスナーを入力フィールドに追加し、オーバーレイの現在の位置を計算し、位置を絶対に変更し、上/左の位置を更新してオーバーレイを元の位置に戻すことです。位置が固定されたときに画面を表示し、最後に新しいblurリスナーを追加して、入力にフォーカス/ぼかしを残すときにオーバーレイを固定位置にリセットします。これにより、ページがスクロールしなくなります。 touchstartイベントの前にトリガーする必要があるため、focusを使用することをお勧めします。この場合、ページは既にスクロールを開始します。 Safariは、focusイベントがトリガーされたときに絶対配置オーバーレイを見つけて中央に配置できる必要があります。

1
DKrautkramer

だから私はこれを解決し、私のiPhone 5でテストしました。チェックするiPadを持っていません。無効にするoverflow:hidden私のソリューションでは、すべてのモーダルでスクロールをすべて無効にする場合は、追加できます。解決策は、基本的に高さと位置のプロパティをhtml要素とbody要素の両方に追加することです。

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

したがって、入力に焦点を合わせた場合にのみ、高さと位置が定義され、レポからこのソリューションをすでにコーディングしているので、プルリクエストを送信します。また、gulpセットアップにbrowserSyncを追加しました。したがって、どのデバイスでも簡単にテストできるようになります。

乾杯!

編集:別の方法、上記のソリューションが何らかの理由で機能しない場合。その後、

 /*
  * @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は私にとって魅力のように動作します]

1
Danish

Htmlページでのモーダル入力のバウンスに役立つ複数のことを試しました。私のために働いた最も簡単な解決策は、ページのモーダルが開いているときのbodyタグに次のスタイルを追加することでした。

position: fixed;
width: 100%;
0
Manohar Mankala

100%確信はありませんが、次のことを想像できます。

キーボードが表示されると、ウィンドウの高さは減少しますが、scrollTopの値は同じままなので、サイトはその値にジャンプします。モーダルが開いているときに、bodyoverflow:hiddenを追加できます。これにより、モーダルの「背後」でのスクロールがブロックされ、おそらく問題が解決します。

0
Kilian So

このメタ(maximum-scale = 1、minimum-scale = 1)を追加して、入力フィールドのフォーカス時に発生したスクロールをリセットします。

0
Pranav K