LoginSignup
178
162

More than 5 years have passed since last update.

iOSはoverflow:hidden;でスクロールを無効にできない

Last updated at Posted at 2016-04-14

スクロールを無効にするCSS

html,body{
  overflow: hidden
}

しかしこれではiOSでスクロールを無効にできない.

ページ全体を無効にする方法

// スクロールを無効にする
$(window).on('touchmove.noScroll', function(e) {
    e.preventDefault();
});

// スクロール無効を解除する
$(window).off('.noScroll');

スマホの独自イベントのtouchmoveイベントを切ってスクロールを止める。
解除したい時はoffする。

イベント名に、.noScrollと名前を付けることで、他の部分でtouchmoveイベントを使っていたとしても、そのtouchmoveイベントまでイベントをoff()してしまうこともなく、.noScrollの名前のイベントのみをoff()することができる。

参考

特定のエリアのみスクロールを無効にする方法

ドロワーメニューを左側に表示するときにコンテンツ側を固定するときなど

// スクロールを無効にする
$('.content').on('touchmove.noScroll', function(e) {
    e.preventDefault();
});

// スクロール無効を解除する
$('.content').off('.noScroll');

としても、うまく動くときとうまく動かないときがあった。

しょうがないのでfixして対応した。

// スクロールを無効にする
var scrollTop = $(window).scrollTop();
$('.content').css({'position':'fixed','top':-scrollTop});

// スクロール無効を解除する
$('.content').css({'position':'static','top':'0'});
$('html,body').scrollTop(scrollTop);

私が引っかかってしまったのは、

$('.content').css({'position':'static','top':'0'}).scrollTop(scrollTop);

としてしまったこと。

おまけ

ちなみに作業していたサイトは、

  • レスポンシブでPC,スマホ対応
  • 左ドロワー、コンテンツが右にずれるタイプ
  • スワイプでも操作できる
  • ドロワーをホバーしたらスクロールバーを表示したい・慣性的な動きにしたい
  • ヘッダー固定
  • ドロワーを開いているとき、ドロワー以外をクリック(タップ)したら閉じる
  • ドロワーを開いているときコンテンツはスクロールできない

という仕様だった。(いや、最初は違ったんだ・・・)

当初、sidrというプラグインを使っていた。
途中でヘッダー固定になり、いろいろ書き加えたところ、iPad,Androidタブレットでうまく動かなくなった。
ドロワーを閉じると、Chromeは上へ、Safariは下へ、Firefoxは下へ少しずれる。。。iPhoneも発生するものと発生しないものが・・・(/-\ )
右ドロワーなら問題なかった。
それがプラグインの仕様のようだったので、違うプラグインを探した。
いろいろ検証した結果slideoutというのが一番理想に近いことができそうだったので、これで頑張ることにした。

他にも、
iOSでページトップで上にスクロールしようとするとドロワーメニューが見えてしまう。
ページが全て読み込まれる前にスクロールするとヘッダーの上に隙間ができる。(これは対応していない)
ドロワーメニューのスクロール位置が次開いたときにも引き継がれている。
IE11だけドロワーを開いたときヘッダーが右に移動しない。

などなどいろいろありました。

また、このプラグインは、touchstartがうまく動かないようで、/に遷移してしまう症状もありました。

var _touch = ('ontouchstart' in document) ? 'touchstart' : 'click';
$('.menu').on(_touch,function(){});

こんな感じの使い方はできませんでした。

最終的に、ざっくりとですがこんな感じで実装しました〜

<script src="/js/slideout.min.js"></script>

<script>
    $(function(){

        var ua = navigator.userAgent.toLowerCase(),
                isIE11 = (ua.indexOf('trident/7') > -1);

        var slideout = new Slideout({
            'panel': document.getElementById('panel'),
            'menu': document.getElementById('menu'),
            'padding': 260,
            'duration' : 200
        });

        var scrollTop = $(window).scrollTop(),
                header = $('header'),
                panel = $('#panel'),
                drawer = $('#menu'),
                close = $('.drawer-close'),
                fadeSpeed = 100;

        $('.js-slideout-toggle').on('click',function(){
            slideout.toggle();
        });

        slideout.on('beforeopen', function() {
            if(isIE11){
                header.css({'top':'0'});
                header.animate({'left':'280px'},200);
            }else{
                scrollTop = $(window).scrollTop();
                header.css({'top':scrollTop});
                panel.css({'position':'fixed','top':-scrollTop});
            }
            drawer.show();
        });

        slideout.on('open', function() {
            header.css({'top':scrollTop});
            close.css({
                'z-index':'999999',
                'display':'block'
            });
        });

        slideout.on('beforeclose', function() {
            if(isIE11) {
                header.animate({'left':'0'},200);
            }
        });

        slideout.on('close', function() {
            header.css({'top':'0'});
            panel.css({'position':'static','top':'0'});
            $('html,body').scrollTop(scrollTop);
            close.css({
                'z-index':'1',
                'display':'none'
            });
            drawer.hide();
            $('html').removeClass('slideout-open');
        });

    });
</script>
<nav id="menu" class="slideout-menu">
  <div class="js-slideout-toggle">x</div>
  <div>
    メニュー
  </div>
</nav>

<main id="panel" class="slideout-panel">
  <header>
    <div class="js-slideout-toggle">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <h2>Panel</h2>
  </header>
  <div>
    コンテンツ
  </div>
  <div class="drawer-close js-slideout-toggle"></div>
</main>
.slideout-menu{
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    z-index: 0;
    width: 280px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: none;
}
.slideout-panel{
    position: relative;
    background-color: #fff;
    z-index: 2;
}
.slideout-open,
.slideout-open body,
.slideout-open .slideout-panel {
    overflow: hidden;
}
.slideout-open .slideout-menu {
    display: block;
}

.drawer-close {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
}

そういえば、初回アクセス時はドロワーが表示されていて、しばらくしたら閉じるという仕様だったな・・・
他にも案を出したが採用されず、cookieを使ってプラグインの仕様に合わせるためにゴリゴリしたら、やっぱりいらないってなったなぁー・・・w(でしょうねw)

他にもいろいろゴリゴリした。
なんだかんだ久しぶりにがっつりで楽しかったな〜

178
162
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
178
162