2023-02-03
Posted by
先に完成形を見せましょう
完成形
一応ボタンも使えますし
モバイルも対応してますし
スクロールも無効化できます
idも使わないで大丈夫ですし
targetを使う必要もありません
(
今回はcssで#modalを使ってますが可読性を向上させる事が目的の為classでも問題はありません
)
どうです?、Jsを使った物と区別出来ないでしょう
作る
では早速作っていきましょう
まずはhtmlを書きます
<body>
<button class="open">open modal</button>
<div id="modal">
<a href="#" class="_">
<p>CSS Modal</p>
<p>cssだけでモーダルって作れるのかな、でも仮に作れたとしてもUX低そうだからなんかな、js最高!</p>
<img src="/images/blog/00059-3181815356.png"/>
<button>ボタンが大丈夫な事を証明する用</button>
<button class="close">close modal</button>
</a>
</div>
</body>
今回のプログラムは割と自由で.open
や#modal
はbody
の下にあればdiv
などで囲っていても問題ないはずです
これから作る機能としては.open
がクリックされたら#modal
を表示し.close
がクリックされたら非表示にするだけです
cssにはclickイベントがありませんから:is(:active, :focus)
を使わないといけないのが少し面倒ですが大した事はありません
とりあえずモーダルのギミックを作る前に最低限のcssを書いておきます
デザインですから参考程度に見ても大丈夫です
とりあえずモーダルは基本隠すのでdisplay: none;
にしておきましょう
* {box-sizing: border-box;}
p:first-child {
color: #222;
font-size: 21px;
}
p {
color: #222;
font-size: 12px;
margin: 0;
}
#modal {
display: none;
width: 100vw;
height: 100vh;
background-color: #00000050;
position: fixed;
top: 0;
left: 0;
align-items: center;
justify-content: center;
}
._ {
width: 300px;
height: 200px;
background-color: #fff;
border-radius: 4px;
padding: 16px;
text-decoration: none;
cursor: default;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.close {
color: #fff;
background-color: #d31510;
border: none;
font-size: 16px;
font-weight: 600;
border-radius: 4px;
padding: 16px 16px;
}
当たり前ですがまだ何も起きません
これだとつまらないのでとりあえずボタンを押したときに表示されるようにしましょう
body:has(.open:focus) #modal {
display: flex;
}
セレクターが複雑になってきたので日本語訳を少し
body:has(.open:focus) #modal
bodyに.openがクリックされたものが含まれる時の#modal
これでも良いのですが本体をクリックした時に閉じてしまいます追加しましょう
#modal:has(*:not(.close):is(:active, :focus)) {
display: flex;
}
これで.open
がクリックされた時いがいにもモーダルの中にある要素がクリックされた時にも表示されるようになりました
#modal:has(
*
:not(.close):is(:active, :focus))
モーダルに含まれる.close意外の何かがクリックされたとき
:not(.close)
は.close
がクリックされた時はdisplay: flex
ではなくdisplay: none;
にしたいからです
最後にモーダルの表示中にスクロールが出来ないようにすれば完成です
body:has(.open:is(:active, :focus)),
body:has(#modal *:not(.close):is(:active, :focus)) {
overflow: hidden;
}
body:has(.open:is(:active, :focus))
bodyに.openがクリックされた物が含まれている時
body:has(#modal
*
:not(.close):is(:active, :focus))
bodyにモーダルの中の.close意外に何かクリックされたものが含まれている時
最終的なコード
<body>
<button class="open">open modal</button>
<div id="modal">
<a href="#" class="_">
<p>CSS Modal</p>
<p>cssだけでモーダルって作れるのかな、でも仮に作れたとしてもUX低そうだからなんかな、js最高!</p>
<img src="/images/blog/00059-3181815356.png"/>
<button>ボタンが大丈夫な事を証明する用</button>
<button class="close">close modal</button>
</a>
</div>
</body>
* {box-sizing: border-box;}
body {
padding: 16px;
}
img {
border-radius: 4px;
}
p:first-child {
color: #222;
font-size: 21px;
}
p {
color: #222;
font-size: 12px;
margin: 0;
}
#modal {
display: none;
width: 100vw;
height: 100vh;
background-color: #00000050;
position: fixed;
top: 0;
left: 0;
align-items: center;
justify-content: center;
}
._ {
width: 300px;
height: 460px;
background-color: #fff;
border-radius: 4px;
padding: 16px;
text-decoration: none;
cursor: default;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.close {
color: #fff;
background-color: #d31510;
border: none;
font-size: 16px;
font-weight: 600;
border-radius: 4px;
padding: 16px 16px;
}
body:has(.open:focus) #modal,
#modal:has(*:not(.close):is(:active, :focus)) {
display: flex;
}
body:has(.open:is(:active, :focus)),
body:has(#modal *:not(.close):is(:active, :focus)) {
overflow: hidden;
}
おまけ
これには少し欠点があります
これの一つはクリックした時にページを移動してしまう事です、これはJSを使いデフォルトのイベントの発生をキャンセルすることで解決出来ます
<button class="open">open modal</button>
<div id="modal">
<a href="#" class="_">
<p>CSS Modal</p>
<p>cssだけでモーダルって作れるのかな、でも仮に作れたとしてもUX低そうだからなんかな、js最高!</p>
<button>なんかするボタン</button>
<button class="close">close modal</button>
</a>
</div>
<script>
document.querySelector("._").addEventListener("click", (e) => {
e.preventDefault();
})
</script>
react
<div id="modal">
<a href="#" className="_" onClick={(e) => e.preventDefault()}>
<p>CSS Modal</p>
<p>cssだけでモーダルって作れるのかな、でも仮に作れたとしてもUX低そうだからなんかな、js最高!</p>
<button>なんかするボタン</button>
<button className="close">close modal</button>
</a>
</div>
このドキュメントどう?