iOSでスクロールできないようにする

iOSでモーダルやハンバーガーメニューを開いている時に、スクロールで背景のコンテンツがスクロールされないようにする方法を調べたのでメモ。

うまくいかなかった例

今回は簡単なモーダルを実装してみます。

HTML

<header class="header">ヘッダー</header>
<div class="contents">
	<p>コンテンツ本文コンテンツ本文コンテンツ本文コンテンツ本文</p>
	<p>コンテンツ本文<button class="modal-link" data-modaibody="modal01">モーダル01</button>コンテンツ本文コンテンツ本文コンテンツ本文</p>
	~略~
	<p>コンテンツ本文コンテンツ本文コンテンツ本文コンテンツ本文</p>
</div>
<footer class="footer">フッター</footer>

<div class="modal-bg"></div>
<div class="modal-contents">
	<button class="modal-close">閉じる</button>
	<div class="modal-scroll">
		<div id="modal01" class="modal-body">
			<p>モーダル01の中身です。</p>
		</div>
		<div id="modal02" class="modal-body">
			<p>モーダル02の中身です。</p>
			~略~
			<p>モーダル02の中身です。</p>
		</div>
	</div>
</div>

.modal-contentsがモーダル部分で.modal-bodyがモーダルの各中身、.modal-scrollで中身が長い時にスクロールできるようにしています。

CSS

html.is-fixed,
html.is-fixed body {
	overflow: hidden;
}
.modal-bg {
	display: none;
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: rgba(0, 0, 0, 0.4);
}
.modal-bg.is-show {
	display: block;
}
.modal-contents {
	display: none;
	position: fixed;
	top: 50%;
	left: 50%;
	width: 300px;
	height: 300px;
	transform: translate(-50%, -50%);
	background: #ffffff;
}
.modal-contents.is-show {
	display: block;
}
.modal-scroll {
	height: 100%;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	overflow-scrolling: touch;
}
.modal-body {
	display: none;
}
.modal-body.is-show {
	display: block;
}
.modal-close {
	position: absolute;
	top: -30px;
	right: 0;
}

各要素にclassを付与してモーダルを表示させます。

JavaScript

$(function() {
	$('.modal-link').on('click', function() {
		var target = $(this).data('modaibody');
		$('html').addClass('is-fixed');
		$('.modal-bg').addClass('is-show');
		$('.modal-contents').addClass('is-show');
		$('#' + target).addClass('is-show');
	});

	$('.modal-close').on('click', function() {
		$('html').removeClass('is-fixed');
		$('.modal-bg').removeClass('is-show');
		$('.modal-contents').removeClass('is-show');
		$('.modal-body').removeClass('is-show');
	});
});

htmlとbodyにoverflow: hidden;を指定することでPCではスクロールできないようにできるのですが、iOSではスクロールできてしまいます。
うまくいかなかった場合のデモページ
 

対応方法

htmlとbodyにoverflow: hidden;と合わせてheight: 100%;を指定するといいようです。

CSS

html.is-fixed,
html.is-fixed body {
	height: 100%;
	overflow: hidden;
}

対応後のデモページ

ただしこの方法の場合、モーダルを開くとスクロール位置がページトップに戻ってしまいます。
ヘッダーで使用するハンバーガーメニューなどの場合は問題なさそうですが、ページの下部の方にあるモーダルなどの場合には使えません。
この対応方法として、モーダルを開く前のスクロール位置を取得して、閉じた際にスクロール位置を元に戻すことで一応対応はできました。

JavaScript

$(function() {
	var scrollPos;
	$('.modal-link').on('click', function() {
		scrollPos = $(window).scrollTop();
		var target = $(this).data('modaibody');
		$('html').addClass('is-fixed');
		$('.modal-bg').addClass('is-show');
		$('.modal-contents').addClass('is-show');
		$('#' + target).addClass('is-show');
	});

	$('.modal-close').on('click', function() {
		$('html').removeClass('is-fixed');
		$('.modal-bg').removeClass('is-show');
		$('.modal-contents').removeClass('is-show');
		$('.modal-body').removeClass('is-show');
		$(window).scrollTop(scrollPos);
	});
});

スクロール位置対応後のデモページ
ただこの方法でもモーダルを開いている時はスクロール位置がページトップに戻っているので、モーダルの背景が半透明の場合など、デザインによっては違和感があるかもしれません。
 

【参考サイト】

 

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2024年12月
1234567
891011121314
15161718192021
22232425262728
293031