[CSS] ボタン押下で表示するサブウインドウをCSSだけで実装したい
- フォームの入力画面を、ボタンクリックで表示したサブウインドウに置いているサイトがあります
- セミナーや資料の申し込みページなど、一つのページに複数のフォームを設置するときに入力フォームをサブウインドウ化することで、ページ全体のボリュームを圧縮することができます
- 一見すると動的なサブウインドウの表示も、JavascriptやjQueryを使わずに、htmlと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属性を区別する必要があります
- 同じidのままだと、ウインドウA用のボタンを押したのにウインドウBが開くといった紐付けのずれが起きてしまいます
<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>
- サブウインドウAでは、inputタグのidとlabelのfor属性を「flag_sub_window_01」にし、もう一方のサブウインドウBでは「flag_sub_window_02としています」
ご質問など受け付けています
記事の中でわかりにくかったところ、もっと知りたかったこと、間違っていることなど、何でもお気軽にご連絡ください。
ご連絡は下記フォームを利用いただくか、ツイッターアカウント@flat8migi宛てでもOKです。