【jQuery無し】javascriptを使った複数モーダルビュー
昨今のフロントエンド界隈ではvueやReactなどのフレームワークを使った開発が盛んになっていますが、それでもなお「WordPress」を筆頭に従来のホームページ制作もまだまだ需要があるのが現状です。
この記事では素のjavascriptを使ったモーダルビューの実装を行います。素のjavascriptを使ったDOM操作を行うことは業務上減ってきているかと思いますので、どちらかというと初学者向けということになります。
早速つくる
※追記:2021.07.12
1ページ内に複数のジャンルのモーダルを設置しても機能するよう変更。
(例:ギャラリーのモーダルとスタッフ紹介のモーダルを1ページの中に共存させる)
サンプルは非常にシンプルにしてあります。スタイルなどは各々良い感じにしていただければと思います。
完成の挙動はこちらから。
htmlとCSSを用意
まずは以下のようにボタンと、モーダルで表示させる内容を用意します。
<section data-modal="modal1">
<button class="modal-trigger" data-target="1">ボタン1</button>
<button class="modal-trigger" data-target="2">ボタン2</button>
<button class="modal-trigger" data-target="3">ボタン3</button>
<!--これより下がモーダルで表示させるコンテンツ-->
<div id="1" class="modal" data-content="modal1">
<div class="close-btn">
<span></span>
<span></span>
</div>
<p>モーダル1</p>
</div>
<div id="2" class="modal" data-content="modal1">
<div class="close-btn">
<span></span>
<span></span>
</div>
<p>モーダル2</p>
</div>
<div id="3" class="modal" data-content="modal1">
<div class="close-btn">
<span></span>
<span></span>
</div>
<p>モーダル3</p>
</div>
</section>
data
属性が、今回モーダルを操作する上で重要になります。
-
data-modal
全体をラップする(親要素)につけます。insertBefore()
をするときに必要 -
data-target
クリックしたものと表示させるコンテンツの対応に利用します。具体的には、クリックしたdata-target属性の値と同じid名のコンテンツを表示させています。 -
data-content
insertBefore()
するときの挿入場所です。insertBefore()は、親要素となるラッパーの(今回だとsectionタグ)中にある任意の要素を検索して、その検索した要素の前に新たな要素をインサートします。
親要素が見分けられればなんでもいいのですが、idにしてしまうと1ページの中に1つしか使えなくなってしまいます。
そこで、data属性を利用します。data属性であれば、値を変更して何個でも親要素を作成することができます。
.modal{
visibility: hidden;
opacity: 1;
transition:all 500ms ease;
position:relative;
background:#000;
color:#fff;
}
.open-modal + .modal{
visibility: visible;
opacity: 1;
}
.close-btn{
span{
position:absolute;
top:0px;
right:100px;
border-bottom: 2px #FFF solid;
width: 40px;
height: 1px;
display: block;
right:0px;
top:16px;
transform: rotate(45deg);
&:first-child{
transform: rotate(-45deg);
}
}
}
簡単に解説をすると、modal-trigger
というクラス名のボタンを用意し、data属性を設定します。
modal-trigger
をjavscriptで監視し、クリックイベントをトリガーにmodal
を表示させます。
data属性は、どのボタンをクリックしたのかの判定に利用します。
data属性の値と、対応するモーダルコンテンツのid属性の値を同じにしておくところがポイントです。
js
あとはjsで操作します。
初めに言葉で説明すると、eventListenerでmodal-trigger
を監視し、クリックイベントをトリガーとしてopen-modal
というクラスをもった<span>
タグを、表示させたいコンテンツの前に挿入します。
モーダルのトリガーとなるボタンやコンテンツは複数あるので、id属性は使えません。
クラスを付与することになるので、querySelectorAll()
メソッドを使います。このメソッドは、取得した値をforeach
で回せることがポイントです。
クリックしたボタンのdata属性と一致するidを持つコンテンツを表示させるようにします。
閉じる時も同じ原理です。
close-btn
のクリックイベントをトリガーに、.open-modal
クラスを外します。
var hideModal = function(c){
c.forEach(function(target){
target.addEventListener("click", function(){
var closeModal = document.querySelector('.open-modal');
closeModal.classList.remove('open-modal');
});
});
}
//modalを監視
var modalTrigger = function(c){
c.forEach(function(target){
target.addEventListener('click',function(event){
//data属性でクリックした対象を判定
var dataTarget = target.getAttribute("data-target");
var content = document.getElementById(dataTarget);
//モーダルの親ラッパー
var parents = document.querySelectorAll('section[data-modal]');
parents.forEach(function(p){
//挿入するspanタグ
console.log(p);
if(p.dataset.modal == content.dataset.content){
var spn = document.createElement('span');
spn.className = "open-modal absolute"
p.insertBefore(spn, content);
}
});
});
})
}
window.addEventListener('DOMContentLoaded', function(){
//modalを監視
var modalContent = document.querySelectorAll(".modal-trigger");
modalTrigger(modalContent);
//modalを閉じる
var closeBtn = document.querySelectorAll(".close-btn");
hideModal(closeBtn);
})
jQueryやその他ライブラリを使えばもっと簡単ですが、DOM操作を慣れるにはちょうど良い機能だと思います。
アニメーションなどはCSSでつける方が簡単かと思います。
以上。
Discussion