やること
あらゆるOSにおいて、スクロールがあるハンバーガーメニューを表示している間、背景のスクロールは動かないようにする。
まえおき
基本的に、スクロールさせるには overflow : scroll;
、スクロールをしないようにするにはoverflow: hidden;
を使うことが一般的。
アプリケーションのhtml
タグには初期値でoverflow : scroll;
がついている。
そのため、わざわざoverflow : scroll;
を当てなくてもスクロールできるようになっている。
###ちなみに
html
タグにoverflow: hidden
をつけてみてください。ほとんどの場合、スクロールがを防げます。
このほとんどというのがどういうことか後ほどわかります。
#実装前のCSSとJSのコード
##ハンバーガーメニューのCSS
.humburger-menu {
/*スクロールするようにする*/
overflow: scroll;
/*ハンバーガーをその場に固定*/
position: fixed;
/*上端との距離*/
top: 0;
/*高さ画面いっぱい*/
height: 100%;
/*滑らかスクロール*/
-webkit-overflow-scrolling: touch;
}
##ハンバーガーメニューを開け閉じするJavaScript
function slideIn(){
// 見やすくするためにするために変数を作成
var menu = $('.humburger-menu'), // 開け閉じする要素
menuBtn = $('.hamburger_button'), // メニューボタン
body = $(document.body),
menuWidth = menu.outerWidth();
// メニューボタンをクリックした時の動き
menuBtn.on('click', function(){
// body に open クラスをつけたりはずしたりする( open クラスは空)
body.toggleClass('open');
if(body.hasClass('open')){
// open クラスが body についていたらメニューをスライドインする
body.animate({'right' : menuWidth }, 200);
menu.animate({'right' : 0 }, 200);
} else {
// open クラスが body についていなかったらスライドアウトする
menu.animate({'right' : -menuWidth }, 200);
body.animate({'right' : 0 }, 200);
}
});
};
試したこと
1. htmlタグに overflow: hidden; を直接つける
function slideIn(){
var menu = $('.humburger-menu'),
menuBtn = $('.hamburger_button'),
body = $(document.body),
menuWidth = menu.outerWidth();
menuBtn.on('click', function(){
body.toggleClass('open');
if(body.hasClass('open')){
body.animate({'right' : menuWidth }, 200);
menu.animate({'right' : 0 }, 200);
$('html').css('overflow':'hidden') // 追記
} else {
menu.animate({'right' : -menuWidth }, 200);
body.animate({'right' : 0 }, 200);
$('html').css('overflow':'scroll') // 追記
}
});
};
これでほとんど動きます。
しかし、、iOSで正常に動作しません!!
Android, PC : ハンバーガーメニューをスクロールしても背景は動かない
iOS : ハンバーガーメニューをスクロールすると背景もスクロールされる
というわけで不採用!!
2. htmlタグに overflow: hidden; を含むclassつける
新しいCSS class
.scroll-prevent {
overflow: hidden;
}
function slideIn(){
var menu = $('.humburger-menu'),
menuBtn = $('.hamburger_button'),
body = $(document.body),
menuWidth = menu.outerWidth();
menuBtn.on('click', function(){
body.toggleClass('open');
if(body.hasClass('open')){
body.animate({'right' : menuWidth }, 200);
menu.animate({'right' : 0 }, 200);
$('html').addClass('scroll-prevent') // 追記
} else {
menu.animate({'right' : -menuWidth }, 200);
body.animate({'right' : 0 }, 200);
$('html').removeClass('scroll-prevent') // 追記
}
});
};
これは完全にダメ元でやりましたね。
1.
の結果と同じです...
3. htmlタグに position: fixed; を含むclassをつける
新しいCSS class
.scroll-prevent {
/*動き固定*/
position: fixed;
/*奥行きを管理*/
z-index: -1;
/*下2つで背景を元のサイズのまま表示することができる*/
width: 100%;
height: 100%;
}
function slideIn(){
var menu = $('.humburger-menu'),
menuBtn = $('.hamburger_button'),
body = $(document.body),
menuWidth = menu.outerWidth();
menuBtn.on('click', function(){
body.toggleClass('open');
if(body.hasClass('open')){
body.animate({'right' : menuWidth }, 200);
menu.animate({'right' : 0 }, 200);
$('html').addClass('scroll-prevent') // 追記
} else {
menu.animate({'right' : -menuWidth }, 200);
body.animate({'right' : 0 }, 200);
$('html').removeClass('scroll-prevent') // 追記
}
});
};
できました!!
iOSでも求めていた動作が確認できました!!
ちなみにaddClass
とremoveClass
はtoggleClass
に省略することができます。
こんな風に
function slideIn(){
var menu = $('.humburger-menu'),
menuBtn = $('.hamburger_button'),
body = $(document.body),
menuWidth = menu.outerWidth();
menuBtn.on('click', function(){
body.toggleClass('open');
$('html').toggleClass('scroll-prevent') // 追記
if(body.hasClass('open')){
body.animate({'right' : menuWidth }, 200);
menu.animate({'right' : 0 }, 200);
} else {
menu.animate({'right' : -menuWidth }, 200);
body.animate({'right' : 0 }, 200);
}
});
};
追記
このままだと、ハンバーガー内のリンク先に飛んだ時に、scroll-prevent
が居残ってしまい、遷移先の画面のスクロールできないことがわかりました。。。
function slideIn(){
var menu = $('.humburger-menu'),
menuBtn = $('.hamburger_button'),
body = $(document.body),
menuWidth = menu.outerWidth();
$('html').removeclass('scroll-prevent') // 追記
menuBtn.on('click', function(){
body.toggleClass('open');
$('html').toggleClass('scroll-prevent')
if(body.hasClass('open')){
body.animate({'right' : menuWidth }, 200);
menu.animate({'right' : 0 }, 200);
} else {
menu.animate({'right' : -menuWidth }, 200);
body.animate({'right' : 0 }, 200);
}
});
};
この追記でつけたした
$('html').removeclass('scroll-prevent')
でscroll-prevent
classをページ遷移時にremoveすることで、初期値に戻し異常なく動くようになりました!
余談
これはハンバーガーだけでなく、モーダルなどでも応用することができそうです。(試してないけど)
デザインなどに応じてCSSの中身を変更することで、柔軟に対応することができると思います。
例えばこんな感じ
.scroll-prevent {
position: fixed;
z-index: -1;
width: 100%;
height: 100%;
top: 0; /*追記*/
right: 0; /*追記*/
}
それでもめんどくさいので、全OSがoverflow: hidden
だけで解決できるようになることを期待して終わります。