cssだけでモーダルウィンドウ
擬似クラスを組み合せてモーダルウインドウを作ったので書き残しておくことにします
レスポンシブにも対応していると思います。
戻るときにアニメーションさせるのがめんどくさかったのできゅっと戻ります
こんな形でもいいよって方はどうぞ
HTMLのコード
今回の作例では簡素なコードにしてみました
画像をボタンにすべくコントロールにはID属性を
画像にはlabel要素を組み合わせてあります
CSSを指定しやすいように順番を整えておくことがキモ
1 2 3 4 5 6 7 8 9 10 |
<div id="modal"> <input type="checkbox" name="modal" id="item1"> <input type="checkbox" name="modal" id="item2"> <input type="checkbox" name="modal" id="item3"> <div class="box"> <label for="item1"><img src="img/animal1.jpg" alt=""></label> <label for="item2"><img src="img/animal2.jpg" alt=""></label> <label for="item3"><img src="img/animal3.jpg" alt=""></label> </div> </div> |
よく見る作例だと背景用の要素が用意されている場合がほとんどですが、ここでは邪魔なので入れずにマークアップしています。 背景用の要素の有無はどっちでもいいと思いますので、今回は無しで行きます
CSS
CSSはアニメーションを多用するのでまずは基本設定の方から
横並びに並べておきます
1 2 3 4 5 6 7 8 9 10 11 12 |
input[type="checkbox"] { display: none; } .box { display: flex; justify-content: space-evenly; width: 80%; margin: 0 auto; } .box label { width: 30%; } |
背景を出すためのコード
画像をクリックしたらまず黒い背景を出していきたいのでこの設定からしていきます。
どこをクリックしても戻れるように背景は「label要素」を使って表示していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@keyframes bg { 0% { opacity: 0; } 100% { background-color: rgba(0, 0, 0, 0.8); opacity: 1; } } #item1:checked ~ .box label[for="item1"], #item2:checked ~ .box label[for="item2"], #item3:checked ~ .box label[for="item3"] { height: 100vh; width: 100%; position: fixed; animation: bg .6s both; display: flex; justify-content: center; align-items: center; z-index: 2; top: 0%; left: 0%; } |
少し冗長な書き方になっていますが、クリックした画像のlabel要素を絞り込んで指定するようにしています。
順番がぐちゃぐちゃですがpositonをfixedにして要素を画面全体に広げています。
画僧のセンタリングはflexで対応。animationプロパティを使ってアニメーションさせています
画像の方のCSS
画像は徐々に大きくなって出てくるような動きにしたいので、こちらもアニメーションを指定しています。 色々な画面幅に対応できるよう最大値を使って指定しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@keyframes img { 0% { width: 0; } 100% { width: 100%; } } .box label img { max-width: 100%; } #item1:checked ~ .box label[for="item1"] img, #item2:checked ~ .box label[for="item2"] img, #item3:checked ~ .box label[for="item3"] img { animation: img .6s .4s both; max-height: 80%; max-width: 80%; object-fit: contain; } |
背景が出てきてから画像を出したいので、アニメーションを遅延させています。
閉じるボタンを設置
今回のものはどこをクリックしても閉じますが、分かりやすいように閉じるボタンも設置します。 擬似要素で追加するのがよさそうなので擬似要素を作りましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#item1:checked ~ .box label[for="item1"]::before, #item2:checked ~ .box label[for="item2"]::before, #item3:checked ~ .box label[for="item3"]::before, #item1:checked ~ .box label[for="item1"]::after, #item2:checked ~ .box label[for="item2"]::after, #item3:checked ~ .box label[for="item3"]::after { content: ""; display: inline-block; height: 3px; width: 30px; background-color: #fff; border-radius: 3px; position: fixed; right: 50px; top: 50px; } #item1:checked ~ .box label[for="item1"]::before, #item2:checked ~ .box label[for="item2"]::before, #item3:checked ~ .box label[for="item3"]::before { transform: rotate(45deg); } #item1:checked ~ .box label[for="item1"]::after, #item2:checked ~ .box label[for="item2"]::after, #item3:checked ~ .box label[for="item3"]::after { transform: rotate(-45deg); } |
画像だけではなくコンテンツを入れたい場合はもう一工夫必要ですが、画像だけであればこのぐらいで書けます。
どうしてもCSSだけで対応したいのであれば一考してみてはいかがでしょうか。
まとめ コピペ用CSS
コンテンツをはめ込む方法は気が向いたときにまとめます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
/*基本 ボタン消したり、横並びにしたり*/ input[type="checkbox"] { display: none; } .box { display: flex; justify-content: space-between; width: 100%; margin: 0 auto; } .box label { width: 30%; } /*基本ここまで*/ /*背景用設定*/ @keyframes bg { 0% { opacity: 0; } 100% { background-color: rgba(0, 0, 0, 0.8); opacity: 1; } } #item1:checked ~ .box label[for="item1"], #item2:checked ~ .box label[for="item2"], #item3:checked ~ .box label[for="item3"] { height: 100vh; width: 100%; position: fixed; animation: bg .6s both; display: flex; justify-content: center; align-items: center; z-index: 100000; top: 0%; left: 0%; } /*背景用ここまで*/ /*画像用*/ @keyframes img { 0% { width: 0; } 100% { width: 100%; } } .box label img { max-width: 100%; } #item1:checked ~ .box label[for="item1"] img, #item2:checked ~ .box label[for="item2"] img, #item3:checked ~ .box label[for="item3"] img { animation: img .6s .4s both; max-height: 80%; max-width: 80%; object-fit: contain; } /*画像用ここまで*/ /*閉じるボタン*/ #item1:checked ~ .box label[for="item1"]::before, #item2:checked ~ .box label[for="item2"]::before, #item3:checked ~ .box label[for="item3"]::before, #item1:checked ~ .box label[for="item1"]::after, #item2:checked ~ .box label[for="item2"]::after, #item3:checked ~ .box label[for="item3"]::after { content: ""; display: inline-block; height: 3px; width: 30px; background-color: #fff; border-radius: 3px; position: fixed; right: 50px; top: 50px; } #item1:checked ~ .box label[for="item1"]::before, #item2:checked ~ .box label[for="item2"]::before, #item3:checked ~ .box label[for="item3"]::before { transform: rotate(45deg); } #item1:checked ~ .box label[for="item1"]::after, #item2:checked ~ .box label[for="item2"]::after, #item3:checked ~ .box label[for="item3"]::after { transform: rotate(-45deg); } /*閉じるボタンここまで*/ |