質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

0回答

1764閲覧

モーダルの表示をした時に背景がスクロールしないようにしたい

yotubarail

総合スコア23

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2021/11/27 12:44

Vue.jsを用いて画面を開いたタイミングでモーダル表示をするように実装しています。
モーダル内ではスクロールを可能にし、背景はスクロールしないようにしたいのですが、うまくいかないためご教授いただければと思います。

試したこと
JavaScriptのtouchmoveとwheelで制御することでモーダル表示の時に背景となるメイン画面がスクロールしないように実装をしようと試みました。
モーダル表示時に画面全体を覆うような薄い黒色の背景をつける都合上、JavaScriptの処理自体は行われてもスクロールができてしまいます。

該当のコードは以下の通りです。

メイン画面

vue

1<template> 2 <div> 3 <Modal v-if="isModal" @closeModal="closeModal" @stop="stop"/> 4 <div class="hello" ref="main"> 5 <button @click="stop()">ストップ</button> 6 <button @click="start()">スタート</button> 7 <button @click="openModal()">ダイアログ開く</button> 8 <p> 9 For a guide and recipes on how to configure / customize this project,<br> 10 check out the 11 <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>. 12 </p> 13 <h3>Installed CLI Plugins</h3> 14 <ul> 15 <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li> 16 <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li> 17 </ul> 18 <h3>Essential Links</h3> 19 <ul> 20 <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li> 21 <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li> 22 <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li> 23 <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li> 24 <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li> 25 </ul> 26 <h3>Ecosystem</h3> 27 <ul> 28 <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li> 29 <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li> 30 <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li> 31 <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li> 32 <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li> 33 </ul> 34 </div> 35 </div> 36</template> 37 38<script> 39import Modal from "@/components/modal.vue" 40export default { 41 components: { 42 Modal 43 }, 44 data() { 45 return { 46 isModal: false, 47 } 48 }, 49 methods: { 50 handleTouchMove(event) { 51 event.preventDefault(); 52 }, 53 stop() { 54 const main = this.$refs.main; 55 main.addEventListener('touchmove', this.handleTouchMove, { passive: false }); 56 main.addEventListener('wheel', this.handleTouchMove, { passive: false }); 57 }, 58 start() { 59 const main = this.$refs.main; 60 main.removeEventListener('touchmove', this.handleTouchMove, { passive: false }); 61 main.removeEventListener('wheel', this.handleTouchMove, { passive: false }); 62 }, 63 closeModal() { 64 this.isModal = false 65 }, 66 openModal() { 67 this.isModal = true 68 } 69 }, 70 mounted() { 71 this.$nextTick(() => { 72 this.openModal() 73 }) 74 } 75} 76</script>

モーダル

vue

1<template> 2 <div> 3 <div class="modal-bg d-flex justify-content-center h-100 w-100 align-items-center position-fixed" 4 @click.self="clickCloseBtn()" ref="modal"> 5 <div class="bg-white contents" ref="contents"> 6 <p class="mb-2">ダイアログ</p> 7 <p class="mb-2">ダイアログ</p> 8 <p class="mb-2">ダイアログ</p> 9 <p class="mb-2">ダイアログ</p> 10 </div> 11 </div> 12 </div> 13</template> 14 15<script> 16export default { 17 methods: { 18 clickCloseBtn() { 19 this.$emit('closeModal') 20 }, 21 }, 22 mounted() { 23 this.$nextTick(() => { 24 this.$emit('stop') 25 }) 26 } 27} 28</script> 29<style> 30.modal-bg { 31 top:0; 32 left:0; 33 background-color:rgba(0,0,0,0.5); 34 z-index: 10; 35} 36 37.modal-bg .contents { 38 z-index:20; 39 width:80%; 40 height: 10%; 41 overflow: auto; 42} 43</style>

よく方法として目にする
「モーダル表示前のスクロール位置を取得→モーダル表示のタイミングでposition:fixedを設定し、topに先ほど取得したスクロール位置を設定」
といった方法も試したのですが、今回のような画面を開いた時にスクロール位置を取得する場合iPhoneのSafariではスクロール位置の取得がうまくできず、setTImeoutで位置取得の処理を遅らせるといった方法を取ることになりそうです。
どれくらいの時間遅らせるかといった当たりをつけて実装をするのはベストとは言えないと考えています。
実装としては以下のようになるイメージです。

vue

1this.$nextTick(() => { 2 window.scrollTo(0,scrollHeight); 3 setTimeout(function() { 4 this.scrollPosition = window.scrollY; //ここで取得したスクロール位置をtopに設定する 5 this.isModal = true 6 }, 500) 7})

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問