Edited at

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

More than 1 year has passed since last update.


スクロールを無効にする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)

他にもいろいろゴリゴリした。

なんだかんだ久しぶりにがっつりで楽しかったな〜