ミギムキ

[CSS] ボタン押下で表示するサブウインドウをCSSだけで実装したい

ボタン押下で表示するサブウインドウ

動作イメージ

サンプルコード

html

<label for="flag_sub_window" class="open_sub_window">サブウインドウを開く</label> <input type="checkbox" id="flag_sub_window" class="check_sub_window"> <label for="flag_sub_window" class="bg_sub_window"> <label for="dummy_sub_window" class="sub_window"> <label for="flag_sub_window" class="close_sub_window"></label> <div class="sub_window_content"> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> <p>テストテストテストテストテストテストテストテストテストテスト</p> </div> </label> </label>

CSS

.open_sub_window { display: block; width: 15em; padding: 1em 2em; border-radius: 10px; background-color: #3388dd; color: #fff; text-align: center; cursor: pointer; } .open_sub_window:hover { opacity: 0.8; } .check_sub_window { display: none; } .bg_sub_window { display: block; position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; background-color: rgba(0, 0, 0, 0.5); visibility: hidden; opacity: 0; pointer-events: none; } .bg_sub_window:hover { transition: 0.5s; } .check_sub_window:checked + .bg_sub_window { visibility: visible; opacity: 1; pointer-events: auto; transition: 0.5s; } .sub_window { position: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%); padding: 30px; max-height: 90%; background-color: #fff; overflow-y: auto; } @media screen and (max-width: 767px) { .sub_window { width: calc(100% - 20px); } } @media print, (min-width: 768px) { .sub_window { width: 90%; max-width: 900px; } } .close_sub_window { position: absolute; top: 10px; right: 10px; transform: rotate(45deg); border: none; outline: none; width: 30px; height: 30px; } .close_sub_window::before, .close_sub_window::after { position: absolute; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%); background-color: #3388dd; content: ""; } .close_sub_window::before { width: 60%; height: 3px; } .close_sub_window::after { width: 3px; height: 60%; } .close_sub_window:hover { cursor: pointer; } .sub_window_content { display: table; margin: 0px auto; }

サンプルコードの解説

ウインドウ表示の仕組み

<label for="flag_sub_window" class="open_sub_window">サブウインドウを開く</label> <input type="checkbox" id="flag_sub_window" class="check_sub_window"> <label for="flag_sub_window" class="bg_sub_window"> <label for="dummy_sub_window" class="sub_window"> <label for="flag_sub_window" class="close_sub_window"></label> <div class="sub_window_content"> 〜〜〜 </div> </label> </label>
  • ウインドウの動的な表示/非表示は、チェックボックスの「:checked」セレクタを活用して行います
  • チェックボックスには「flag_sub_window」というidと「check_sub_window」というクラスを設定しています
  • ウインドウを表示するボタン「open_sub_window」と、ウインドウを含む背景全体の要素である「bg_sub_window」、ウインドウ内の×アイコン「close_sub_window」は、labelタグで作成しています
  • labelタグのfor属性にチェックボックスのid「flag_sub_window」を設定することでチェックボックスと紐付けています
.check_sub_window:checked + .bg_sub_window { z-index: 9999; opacity: 1; pointer-events: auto; transition: 0.5s; }
  • 表示切り替えをしているスタイルです
  • ボタン「open_sub_window」をクリックすると、for属性で紐付くチェックボックス「check_sub_window」にチェックがつきます。チェックがつくことによりセレクタ「:checked」が有効となります
  • チェックボックスの次要素である「bg_sub_window」に対して、「+」を使ったセレクタでウインドウを表示するスタイルを設定することで、ボタン操作でウインドウが開くようになります
  • ウインドウが開いている状態で、背景「bg_sub_window」と×アイコン「close_sub_window」がクリックされると、セレクタ「:checked」が無効になり、背景「bg_sub_window」が非表示になります

ウインドウ内の要素がクリックされたときにウインドウをクローズさせないための対策

<label for="dummy_sub_window" class="sub_window"> <label for="flag_sub_window" class="close_sub_window"></label> <div class="sub_window_content"> 〜〜〜 </div> </label>
  • ウインドウである「sub_window」もlabelタグで作成していますが、for属性が「dummy_sub_window」となっています
  • これはウインドウの中に置いた入力フォームなどの要素がクリックされたとき、背景「bg_sub_window」クリック時のクローズ処理が働くのを防ぐためにこのような形にしています
  • for属性は空でもよいですが、ダミーであることを明確にするため「dummy_sub_window」としています

Chrome限定の表示問題対策

.bg_sub_window:hover { transition: 0.5s; } .check_sub_window:checked + .bg_sub_window { visibility: visible; opacity: 1; pointer-events: auto; transition: 0.5s; }
  • ウインドウをふわっと表示するために、背景「bg_sub_window」に「transition: 0.5s;」を設定しています
  • しかし、単に「bg_sub_window」で「transition: 0.5s;」とすると、画面リロード時に一瞬、背景とウインドウがふわっと見えてしまいます
  • これはChrome限定の問題で、IE Edge、IE11、Firefoxでは発生しません。ある意味ではChromeがCSSに忠実な動きをしているとも言えます
  • この対策として「transition: 0.5s;」を2つの条件に分けて設定しています
  • 「.check_sub_window:checked + .bg_sub_window { 〜〜〜 }」は、ウインドウを開くとき、「.bg_sub_window:hover」はウインドウを閉じるときにそれぞれ対応します
  • 画面リロード時にはどちらの条件にも当てはまらなくなるため、ふわっと表示されるのを防ぐことができます

一つのページにウインドウを複数設置する場合

<label for="flag_sub_window_01" class="open_sub_window">サブウインドウAを開く</label> <input type="checkbox" id="flag_sub_window_01" class="check_sub_window"> <label for="flag_sub_window_01" class="bg_sub_window"> <label for="dummy_sub_window" class="sub_window"> <label for="flag_sub_window_01" class="close_sub_window"></label> <div class="sub_window_content"> 〜〜〜 </div> </label> </label> 〜〜〜 <label for="flag_sub_window_02" class="open_sub_window">サブウインドウBを開く</label> <input type="checkbox" id="flag_sub_window_02" class="check_sub_window"> <label for="flag_sub_window_02" class="bg_sub_window"> <label for="dummy_sub_window" class="sub_window"> <label for="flag_sub_window_02" class="close_sub_window"></label> <div class="sub_window_content"> 〜〜〜 </div> </label> </label>

ご質問など受け付けています

記事の中でわかりにくかったところ、もっと知りたかったこと、間違っていることなど、何でもお気軽にご連絡ください。

ご連絡は下記フォームを利用いただくか、ツイッターアカウント@flat8migi宛てでもOKです。