【CSS】主要ブラウザに対応した疑似クラス :modalを使って、モーダルを作ってみる！

## はじめに
みなさんは、`:modal`という疑似クラスをご存知でしょうか？

実は、先日Chrome 105とEgde 105がリリースされ、コンテナクエリ`@container`と疑似クラス`:has()`と一緒に疑似クラス`:modal`もサポートされました。


なので今回は、`:modal`の具体的な内容の紹介と`:modal`を使った実装方法の解説を行います。


## 疑似クラス `:modal` とは？
疑似クラス `:modal`は以下の状態の要素のスタイルを変更することができます。

:::note
・ **JavaScriptの `showModal()`によって、表示された要素**
・ **JavaScriptの`requestFullscreen()`によって、全画面表示された要素**
::: 

これら状態で、疑似クラス `:modal`で指定したスタイルを当てることができます。
具体的に、それぞれの状態を解説していきます!

### JavaScriptの `showModal()`によって、表示された要素
↓こちらを例に解説していきます！
ボタンを押すとモーダルが表示されるはずです。
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="yLjeEKY" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/yLjeEKY">
  疑似クラス :modal - 1</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### HTMLについて
```HTML
<button id="button">ダイアログを表示する</button>

<dialog id="dialog">
  ダイアログ要素
  <button id="cancelButton">閉じる</button>
</dialog>
```

HTMLはこのようになっています！

dialog要素は、デフォルトで `display: none;`になっており、
`<dialog open>...</dialog>`このようにopen属性を追加することでダイアログを表示することができます。

#### CSSについて
```CSS
dialog:modal {
  background-color: red;
}
```
CSSはこのようになっています！

JavaScriptの `showModal()`によって表示されたdialog要素の背景を赤に変えています。
そのため、dialog要素にopen属性を追加しても、背景は赤くなりません。
![スクリーンショット 2022-09-09 1.20.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/4c9ce6b2-10e3-ec5b-ed67-b417ab1e63bc.png)

#### JavaScriptについて
```javascript
const Button = document.getElementById('button')
const CancelButton = document.getElementById('cancelButton')
const Dialog = document.getElementById('dialog')

Button.addEventListener('click', () => {
  Dialog.showModal(); // dialogを表示
});

CancelButton.addEventListener('click', () => {
  Dialog.close(); // dialogを非表示
});
```

JavaScriptはこのようになっています。

最初の3行でdialogを開くボタンとdialogを閉じるボタン、dialog要素を定義します。

dialogを開くボタンをクリックした時に、`Dialog.showModal()`を実行することで、dialogが表示されます。
こうすることで、疑似クラス`:modal`のスタイルが当たるというわけです。

dialogを閉じるボタンをクリックした時に `Dialog.close();`を実行することで、dialogが非表示になります。




### JavaScriptの`requestFullscreen()`によって、全画面表示された要素
↓こちらを例に解説していきます！
ボタンを押すと全画面表示で`フルスクリーン`が表示されるはずです。
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="GRdoBNV" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/GRdoBNV">
  疑似クラス :modal - 1</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### HTMLについて
```html
<button id="button">フルスクリーンで表示する</button>
<div id="fullScreen">
  フルスクリーン
</div>
```
HTMLはこのようになっています。

ボタンを押すことで、
div要素が全画面表示されるようにします。


#### CSSについて
```css
#fullScreen:modal {
  color: white;
}
```
CSSはこのようになっています。

idが`dialog`の要素(今回だとdiv要素)が全画面表示した時に、
テキストの色が白になるようにします。

ボタンを押す前に、テキストの色が黒になっているのは確認できると思います。


#### JavaScriptについて
```javascript
const Button = document.getElementById('button')
const FullScreen = document.getElementById('fullScreen')

Button.addEventListener('click', () => {
  FullScreen.requestFullscreen();
});
```
JavaScriptはこのようになっています。

最初の2行で、全画面表示にするボタンと、全画面表示される要素を定義します。

全画面表示にするボタンをクリックした時に、`FullScreen.requestFullscreen()`を実行することで、全画面表示される要素が全画面表示されます。

このようにすることで、div要素が全画面表示されたときに疑似クラス`:modal`のスタイルがあたりテキストの色が白に変わります。

## 疑似クラス`:modal` の使用例
### 画像をクリックすることで、画像が拡大表示されるモーダル
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="xxjZaoV" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/xxjZaoV">
  疑似クラス :modal - 1</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


### 画像をクリックすることで、画像が全画面表示される

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="gOzPBzZ" data-editable="true" data-user="sp_degu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/gOzPBzZ">
  疑似クラス :modal - 2</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## まとめ
今回は、先日のChrome 105とEgde 105のリリースによってサポートされた、疑似クラス `:modal`について紹介、解説しました。

疑似クラス `:modal`は、サービスの種類によっては、使う頻度が極端に変わってきそうですが、知っていて損はない疑似クラスだと思います。

今回紹介した画像をクリックすることで画像が拡大される以外にも、いろいろな使い方はできそうです。

ぜひ、この記事を読んで、疑似クラス `:modal`について理解が深まったという方は、💚いいね・:stock:ストックをお願いします。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510