iosでpositionとoverflowを組み合わせてスクロールさせようとするとフリーズ(ロック)する
iosで、ハンバーガーメニューに代表される位置をウィンドウに固定しつつ表示しきれない場合はスクロールさせるコンポーネントで、特定の操作をするとフリーズ(ロック)する不具合を発見しました。
フリーズと言っても少し待つとなおるのでそのままでも良いかと思いますが、気になる場合の調整方法を書き記しておきます。
どんなバグか?
冒頭に書いたとおり、positionプロパティと、overflowプロパティを組み合わせて要素を配置しつつ、中にはいった要素をスクロールして表示する場合、要素の上端までスクロールした状態で下方向にスワイプ(更に上方向に行くような操作)した場合と、下端までスクロールした状態で上方向にスワイプ(更に下方向に行くような操作)をすると、フリーズ(ロック)して操作を受け付けなくなります。
少し待っていると操作を受け付けるようになりますが、神経質がすぎる人はこれにイライラするかと思います。
このバグはiosのSafariはもちろん、Chromeでも起こります。
再現したページを用意しましたので、お手元のiPhone でお試しください
QRコードも設置
対応方法
多くのサイトで対応状況を確認してみたところ、未対応のサイトがほとんどでした。
こんなの対応する必要がないと言う判断だと思いますが、こちらをなんとかしてみます。
QRコードも設置
参考にしたサイト
先人の知恵を借りて対応してみました。
こちらのサイトで紹介されている方法を使えば問題なさそうでしたが、いくつかのサイトで試してみるとうまくいかない時もありましたので、紹介されていた以下の点を参考に、別途cssを調整するのも面倒だったので、jQueryでプラグイン化してみました。
- HTMLの方で2重構造にする
- 2重構造にした外側の要素にpositionプロパティ、overflowプロパティをつける
- 2重構造にした内側の要素は外側の要素よりも1px高くし、クリアランスを用意
- JSでスクロールを監視し、上下の限界までスクロールしたときに作ったクリアランス分ずらすようにする。
サンプルのHTML
HTMLでは前述したように、2重構造になるようマークアップする必要がありますので、このような形にしてみました。
サンプルで使っているモーダルは「Remodal」が簡単に使えるので使っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<link rel="stylesheet" href="remodal.css"> <link rel="stylesheet" href="remodal-default-theme.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> <script src="remodal.min.js"></script> <p style="text-align:center;"> <a data-remodal-target="modal" class="btn">モーダルを開く</a></p> <div class="remodal scroll" data-remodal-id="modal" data-remodal-options="hashTracking:false"> <div class="scroll-inner"> <div class="content">content1</div> <div class="content">content2</div> <div class="content">content3</div> <div class="content">content4</div> <div class="content">content5</div> </div> </div> |
「.scroll-inner」の中に表示したい要素を入れていく形になります。
cssのサンプル
特別必要はありませんが、ウィンドウに固定するための記述は適宜して貰う必要がありますので、「.scroll」に対して指定しておきます。
1 2 3 4 5 6 7 8 9 10 11 |
.scroll { position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 80%; height: 80vh; padding: 20px; overflow: auto; background-color: #fff; } |
jsのサンプル
簡単に作ってみたプラグインを使って調整してみます。DLは以下のリンクから
DLして展開していただくと中にはjsファイルが一つはいっています。
こちらを読み込みつつ起動するコードを書きます
1 2 3 4 5 6 7 8 |
<script src="iosScrollBug.js"></script> <script> $(function() { $(document).on('opening', '.remodal', function() { $('.scroll').bugios(); }); }); </script> |
モーダルが開いたときに動かしたいのでこのようなイベントに入れた形です。
「bugios()」というメソッドの形で動くように作ってあるので、対象の要素をセレクタにするだけで完了です
それぞれの環境にあった形に実行するタイミングを適宜変えてもらえばいいと思います。
紹介したサイトで紹介されているコードが一番だと思いますが、状況によってうまく行かず(やってた人のミスかも知れません)、今回紹介したものだと動いたという例もあったので、公開してみましたが汎用性は低いかなと思います。
手軽に試せると思うので困ったときに試してもらうといいかもしれません。