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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

925閲覧

【Javascript】モーダルを閉じたときに上に戻らないようにしたい

a_a

総合スコア13

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2023/04/21 18:36

編集2023/04/22 10:40

実現したいこと

モーダルを閉じたときに上に戻らないようにする。

前提

ページ内に複数設置できるモーダルをJavascriptで作っています。
モーダル開いているときも背景を固定したいです。

発生している問題・エラーメッセージ

1回目は、モーダル開く・閉じても背景固定しくれていますが、
2回目の開くまでは背景固定していて、閉じると上へスクロールされてしまいます。
3回目も開くまでは背景固定、閉じると上へ戻ります。

試したこと

「 window.pageYOffset 」が原因のような気がしますが、どうしたらよいのか分かりません。
よろしくお願い致します(o_ _)o

修正

cssが間違っていたので修正。
javascriptも意図した挙動になるように修正。
cssのクラスを修正した後html側も修正

▼修正後

HTML

1<p><a class="js_mdl_open mdl_open_txt" href="" data-mdlopen="mdl1">モーダル開く</a></p> 2 3<div class="mdl js_mdl" data-mdl="mdl1"><!-- モーダル --> 4 <div class="js_mdl_overlay mdl_overlay"></div> 5 <div class="mdl_wrapper"> 6 <div class="mdl_white"><!-- white --> 7 <div class="mdl_content"><!-- content --> 8 <div class="mdl_close"><span class="mdl_close_icon js_mdl_close_icon"></span></div><!-- 閉じるボタン --> 9 <div class="mdl_main"><!-- main --> 10 <div class="mdl_main_content"> 11 <p>text等が入る</p> 12 </div> 13 </div><!--END main --> 14 </div><!--END content --> 15 16 </div><!--END white --> 17 </div><!--END mdl_wrapper --> 18 </div><!--END mdl -->

▼修正後

CSS

1.mdl { 2 display: none; 3 opacity:0; 4} 5.mdl.mdl_active { 6 display: block; 7 opacity:1; 8 animation-name: mdlactive; 9 animation-duration: .3s; 10 width: 100%; 11 height: 100vh; 12 position: fixed; 13 top: 0; 14 left: 0; 15 background-color: transparent; 16 overscroll-behavior: contain; 17 overflow-y: scroll; 18 z-index: 10000; 19} 20@keyframes modalactive{ 21 from {opacity:0;} 22 to {opacity: 1;} 23} 24.mdl_overlay { 25 position:fixed; 26 top:0; 27 left:0; 28 z-index: 10000; 29 width: 100%; 30 height: 100%; 31 background-color: #000; 32 opacity: 0.7; 33} 34.mdl_wrapper { 35 position:fixed; 36 top:0; 37 left:0; 38 z-index: 10001; 39 width: 100%; 40 height: 100%; 41 padding: 20px; 42 display: flex; 43 justify-content: center; 44 align-items: center; 45} 46.mdl_white { 47 width: min(100%,770px); 48 height: auto; 49 background-color: #fff; 50z-index: 10002; 51} 52.mdl_content { 53 background-color: #fff; 54 width: 100%; 55 height: 100%; 56 max-height: 600px; 57 overflow-y: scroll; 58 overflow-x: hidden; 59 position: relative;/* 閉じるアイコン */ 60} 61.mdl_main { 62 padding: 2em 1.5em; 63} 64.mdl_main_content { width: 100%;} 65/* 閉じるアイコン */ 66.mdl_close { 67 position: absolute; 68 top: 0; 69 right: 0px; 70} 71.mdl_close_icon { 72 display: block; 73 width: 20px; 74 height: 20px; 75 border-radius: 50%; 76 transform: rotate( 45deg); 77 padding-left: 25px; 78 padding-right: 25px; 79 padding-top: 10px; 80 padding-bottom: 40px; 81 margin-top: 10px; 82} 83.mdl_close_icon::before { 84 content: ""; 85 display: block; 86 width: 31px; 87 height: 1px; 88 background-color: #222; 89 transform: translate(-15px,15px); 90} 91.mdl_close_icon::after { 92 content: ""; 93 display: block; 94 width: 1px; 95 height: 31px; 96 background-color: #222; 97} 98.mdl_close_icon:hover { 99 cursor: pointer; 100}

Javascript

1const mdlOpen = document.querySelectorAll('.js_mdl_open');// 開くボタン 2const mdl = document.querySelectorAll('.js_mdl');// モーダル本体 3const body = document.body; 4 5 //モーダル開くイベント発火 6 mdlOpen.forEach( from => { 7 from.addEventListener("click",function(e){ 8 e.preventDefault(); 9 e.stopPropagation(); 10 body.style.top = -(window.pageYOffset) +'px';//fixedより後にきてはダメ 11 12 const datavalue =from.dataset.mdlopen;//dataset値取得(開く) 13 14 mdl.forEach( (to) => { 15 if( datavalue == to.dataset.mdl){ 16 openModal(to); 17 } 18 })//forEach 19 }) 20 })//forEach 21 22 // モーダル開く 23 function openModal(element){ 24 // 背景固定 25 body.style.position = "fixed"; 26 // モーダル表示 27 element.classList.add('modal_active'); 28 29 //モーダル閉じるイベント発火 30 const closebtn = element.querySelector('.js_mdl_close_icon'); 31 closebtn.addEventListener('click', function(e){ 32 e.stopPropagation(); 33 closeModal(element); 34 }); 35 36 //モーダル閉じるイベント発火 37 addEventListener('click', function(e){ 38 e.stopPropagation(); 39 const mdlWrapper = element.querySelector('.js_mdl_wrapper'); 40 if(e.target == mdlWrapper){ 41 closeModal(element); 42 } 43 }) 44 } 45 46 47 // モーダル閉じる 48 function closeModal(mdl){ 49 // topの値取得 50 const scrollY = body.style.top; 51 // モーダル閉じる 52 mdl.classList.remove('modal_active'); 53 // 背景固定解除 54 body.style.position = ""; 55 56 body.style.top = ''; 57 window.scrollTo({ 58 behavior: "instant", 59 left: 0, 60 top: parseInt(scrollY || '0')*-1 61 }); 62 }

▼修正後

Javascript

1 const mdlOpens = document.querySelectorAll('.js_mdl_open');// 開くボタン 2 const mdls = document.querySelectorAll('.js_mdl');// モーダル本体 3 const body = document.body; 4 5 mdlOpens.forEach( mdlOpen => { 6 //モーダル開くイベント発火 7 mdlOpen.addEventListener("click", e =>{ 8 e.preventDefault(); 9 e.stopPropagation(); 10 11 body.style.top = -(window.pageYOffset) +'px';//fixedより後にきてはダメ 12 const datavalue = mdlOpen.dataset.mdlopen;//dataset.mdlopen 13 14 mdls.forEach( (mdl) => { 15 if( datavalue == mdl.dataset.mdl){//dataset.mdl 16 body.style.position = "fixed"; 17 mdl.classList.add('mdl_active'); 18 19 const closebtn = mdl.querySelector('.js_mdl_close_icon'); 20 const mdlOverlay = mdl.querySelector('.js_mdl_overlay'); 21 22 let scrollY = body.style.top;// topの値取得して変数に格納 23 24 closebtn.addEventListener('click',closeModal); 25 mdlOverlay.addEventListener('click',closeModal); 26 27 // モーダル閉じる 28 function closeModal(){ 29 mdl.classList.remove('mdl_active') 30 body.style.position = ""; 31 body.style.top = ''; 32 window.scrollTo({ 33 behavior: "instant", 34 left: 0, 35 top: parseInt(scrollY || '0')*-1 36 }); 37 };//closeModal 38 }//if 39 })//forEach 40 }) 41 })//forEach

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2023/04/21 21:58

あなたが使っている「モーダル」とは何ですか? 自作したもの? Bootstrap Modal, jQuery UI Dialog など利用?
a_a

2023/04/22 01:19

すみません、自作したものです。
退会済みユーザー

退会済みユーザー

2023/04/22 01:28

そうすると推奨していない質問の「コードをください・デバッグしてください等の丸投げの質問」になってしまうのですが⇒ https://teratail.com/help/avoid-asking
ak.n

2023/04/22 04:49

「2回目の開くまでは背景固定していて、閉じると上へスクロールされてしまいます。  3回目も開くまでは背景固定、閉じると上へ戻ります。」 という現象が、確認できませんでした。背景のコンテンツが少ないからですかね。
a_a

2023/04/22 05:26

SurferOnWwwさん そうですね、もう少し色々やってみます。コメントありがとうございますm(__)m
a_a

2023/04/22 05:37

ak.nさん ありがとうございますm(__)m 実際はコンテンツが多いです。 閉じるボタンをクリックしても、overlay部分が反応しています。 モーダル閉じた後にどこかをクリックしても反応しているので、html・cssから見直してみます。
guest

回答1

0

自己解決

  • モーダルを開いた後、クリックするたびに閉じる関数が反応していましたが、クラスがダブっていたことが原因でした。 クラスを変更することで解決しました。

  • 2回目以降、モーダル閉じると上へスクロールしてしまう現象は、「let scrollY = body.style.top;」の記述場所を変更することで解決しました(閉じる関数が呼び出される前に記述)

根本的な解決になっていなかったのでやり直しました。
「let scrollY = body.style.top;」の場所は元に戻して、閉じるイベントをremoveしました。

Javascript

1const mdlOpens = document.querySelectorAll('.js_mdl_open');// 開くボタン 2 const mdls = document.querySelectorAll('.js_mdl');// モーダル本体 3 const body = document.body; 4 5 mdlOpens.forEach( mdlOpen => { 6 //モーダル開くイベント発火 7 mdlOpen.addEventListener("click", e =>{ 8 e.preventDefault(); 9 e.stopPropagation(); 10 body.style.top = -(window.pageYOffset) +'px';//fixedより後にきてはダメ 11 const datavalue = mdlOpen.dataset.mdlopen;//dataset.mdlopen 12 13 mdls.forEach( (mdl) => { 14 if( datavalue == mdl.dataset.mdl){//dataset.mdl 15 body.style.position = "fixed"; 16 mdl.classList.add('mdl_active'); 17 18 const closebtn = mdl.querySelector('.js_mdl_close_icon'); 19 const mdlOverlay = mdl.querySelector('.js_mdl_overlay'); 20 21 closebtn.addEventListener('click',closeModal); 22 mdlOverlay.addEventListener('click',closeModal); 23 24 // モーダル閉じる 25 function closeModal(e){ 26 e.stopPropagation(); 27 e.preventDefault(); 28 let scrollY = body.style.top;// topの値取得して変数に格納 29 mdl.classList.remove('mdl_active') 30 body.style.position = ""; 31 body.style.top = ''; 32 window.scrollTo({ 33 behavior: "instant", 34 left: 0, 35 top: parseInt(scrollY || '0')*-1 36 }); 37 38 closebtn.removeEventListener('click',closeModal); 39 mdlOverlay.removeEventListener('click',closeModal); 40 41 };//closeModal 42 }//if 43 })//forEach 44 }) 45 })//forEach

投稿2023/04/22 09:38

編集2023/04/22 10:14
a_a

総合スコア13

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問