2023-02-03

rust

Posted by

applemango

先に完成形を見せましょう

完成形

一応ボタンも使えますし

モバイルも対応してますし

スクロールも無効化できます

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#modalbodyの下にあれば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>

このドキュメントどう?

emoji
emoji
emoji
emoji