【CSS】こんなメディアクエリの使い方知ってる？

## 概要
みなさんは、メディアクエリ `@media`　をご存じですか？

Webサイトを開発する時に、
ブラウザーのサイズに応じて、スタイルを変えたり、
ユーザーのデバイスに応じて、スタイルを変えたり...

このようにユーザーがWebサイトを見るデバイス・ブラウザーに応じて、
スタイルを変えることができるアットルールの1つです。
*※ アットルールは、`@import` や `@charset` などの@から始まる構文のこと*

そんなメディアクエリ `@media`の基本的な使い方を紹介します。

## メディアクエリの基本的な書き方
メディアクエリは以下のように記述することで、**条件**に合わせて、
スタイルを当てることができます。

```CSS
@media ( /*条件*/ ) {
  .style {
    /*任意のスタイルを記述する*/
  }
}
```

**Sample**
*ブラウザーの横幅が400px以上の時にスタイルが当たるようにしていいます。*
*ブラウザーの横幅の大きさを変えて、ご確認できます*
<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="MWQPGBW" 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/MWQPGBW">
  media query - sampe1</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>


<br />

## メディアクエリで使える条件
### 論理演算子
以下の論理演算子を使うことで、複雑なメディアクエリを記述することができます。

#### `and`
複数の条件を全て満たす時にスタイルを当てることができるようになります。

*例：条件1と条件2を満たす時に、スタイルを当てる*
```CSS
@media (/*条件１*/) and (/*条件2*/) {
    /*任意のスタイルを記述する*/
}
```

#### `not`
複数の条件の1つでも満たさない時にスタイルを当てることができるようになります。
`not`を使うときは、メディアタイプの指定をしないといけません。

例1のように`not`を使うとメディアクエリ全体にnotがかかります。
例2のように`not()`を使うとメディアクエリの1部にnotがかかります。

*例：条件1と条件2が１つでも満たさない時に、スタイルを当てる*
```CSS
@media not all and (/*条件１*/) and (/*条件2*/) {
    /*任意のスタイルを記述する*/
}
```

*例：条件1をみたし、条件2を満たさない時に、スタイルを当てる*
*※ 但し、Media Queries Level 4で対応されるので、すべてのブラウザで使えるわけではありません。*
```CSS
@media all and (/*条件１*/) and (not(/*条件2*/)) {
    /*任意のスタイルを記述する*/
}
```

#### `only`
クエリー全体が一致する場合にのみスタイルを適用します。
`only`を使うときは、メディアタイプの指定をしないといけません。

*例：条件1と条件2を満たす時に、スタイルを当てる*
```CSS
@media only all and (/*条件１*/) and (/*条件2*/) {
    /*任意のスタイルを記述する*/
}
```


#### `,` （カンマ）
`,` （カンマ）は、複数のメディアクエリを1つのルールにまとめるためにしようします。

*例：条件1と条件2には、別のメディアクエリとして扱われます*
```CSS
@media (/*条件１*/), (/*条件2*/) {
    /*任意のスタイルを記述する*/
}
```

<br />

### メディアタイプ
機器の全般的な分類で、スタイルを変更することができます。 
また、`not` または `only` 論理演算子を使用する場合を除き、メディアタイプは省略可能であり、暗黙で all と見なされます。

:::note alert
このメディアタイプはMedia Queries Level 4以降では非推奨です。ご注意ください。
`tty`・`tv`・`projection`・`handheld`・`braille`・`embossed`・`aural`・`speech`
:::


#### `all` 
機器に関係なく、全てでスタイルが当たります。
メディアタイプを省略する場合は、allとして認識されます。

*例：全ての機器で条件1をみたしている時に、スタイルを当てる*
```CSS
@media all and (/*条件*/) {
    /*任意のスタイルを記述する*/
}

/*省略可：上のメディアクエリと同じ*/
@media (/*条件*/) {
    /*任意のスタイルを記述する*/
}
```


#### `print`
ページのある資料や印刷プレビューモードなどの印刷する文書の時にスタイルが当たります。


*例：印刷する文書の時、スタイルを当てる*
```CSS
@media print {
    /*任意のスタイルを記述する*/
}
```

#### `screen`
画面のあるデバイスを利用している時にスタイルが当たります。

*例：画面のあるデバイスの時、スタイルを当てる*
```CSS
@media screen {
    /*任意のスタイルを記述する*/
}
```

<br />

### メディア特性
メディア特性は、ブラウザーやデバイス、環境の特徴によってスタイルを変更することができます。

:::note alert
このメディア特性はMedia Queries Level 4以降では非推奨です。ご注意ください。
`device-width`・`device-height`・`device-aspect-ratio` 
:::


#### `any-hover`
hoverに対応しているデバイスであるかで判断できます。
`any-hover: none`：hoverに対応していないデバイス。スマホなど
`any-hover: hover`：hoverに対応しているデバイス。PCなど

*例：hoverに対応しているデバイスの時にスタイルを当てる*
```CSS
@media (any-hover: hover) {
    /*任意のスタイルを記述する*/
}
```

#### `any-pointer`
ポインティングデバイスであるかで判断できます。
マウスやタッチパネル、ペンタブレット、タッチパッド、トラックボール、ジョイスティックなど..

`any-pointer: none`：利用できるポインティングデバイスがない
`any-pointer: coarse`：正確性が低いポインティングデバイス。高いタップスクリーンなど
　　*※正確性が高いいポインティングデバイスも含む*
`any-pointer: fine`：正確性が高いポインティングデバイス。マウスなど

*例：正確性が低いポインティングデバイスの時にスタイルを当てる*
```CSS
@media (any-pointer: coarse) {
    /*任意のスタイルを記述する*/
}
```


#### `color`
出力機器の色成分（赤, 緑, 青）当たりのビット数に応じて判断できます。
*※ 赤, 緑, 青の中で、最小のビット数の値が使われます。*

`color`：すべてのカラーデバイス
`min-color: 8`：色成分（赤, 緑, 青）が8ビット以上の時
`max-color: 8`：色成分（赤, 緑, 青）が8ビット以下の時


*例：色成分（赤, 緑, 青）が8ビット以上の時にスタイルを当てる*
```CSS
@media (min-color: 8) {
    /*任意のスタイルを記述する*/
}
```


#### `color-gamut`
出力デバイスの色空間に応じて判断できます。

`color-gamut: srgb`：srgb色空間のデバイスの時, 大半のディスプレイがこれ
`color-gamut: p3`：p3色空間のデバイスの時
`color-gamut: rec2020`：rec2020色空間のデバイスの時


*例：srgb色空間のデバイスの時にスタイルを当てる*
```CSS
@media (color-gamut: srgb) {
    /*任意のスタイルを記述する*/
}
```


#### `color-index`
出力デバイスの色参照テーブルの項目数に応じて判断できます。

`color-index`： 色参照テーブルの項目数がある時
`min-color-index: 15000`：色参照テーブルの項目数が15000以上の時
`max-color-index: 15000`：色参照テーブルの項目数が15000以下の時


*例：色参照テーブルの項目数が15000以上の時にスタイルを当てる*
```CSS
@media (min-color-index: 15000) {
    /*任意のスタイルを記述する*/
}
```

#### `display-mode`
表示モードに応じて判断できます。
`display-mode: fullscreen`：利用可能な表示領域が全て利用されている時 
`display-mode:　standalone`： 利用可能な表示領域にステータスバーが含まれていない時
`display-mode: minimal-ui`： 利用可能な表示領域にステータスバー＋URL部分が含まれていない時
`display-mode:`： 利用可能な表示領域にブラウザのインターフェースが全て含まれている時

*例：利用可能な表示領域が全て利用されている時にスタイルを当てる*
```CSS
@media (display-mode: fullscreen) {
    /*任意のスタイルを記述する*/
}
```

#### `forced-colors`
ブラウザーが強制カラーモードを有効にしているかに応じて判断できます。

`forced-colors: none`： 強制カラーモードを有効にしてない時
`forced-colors: active`：　強制カラーモードを有効にしている時


*例：　強制カラーモードを有効にしている時にスタイルを当てる*
```CSS
@media (forced-colors: active) {
    /*任意のスタイルを記述する*/
}
```

#### `grid`
出力デバイスがグリッドベースの画面かに応じて判断できます

`grid: 0`： グリッドベースの画面の時
`grid: 1`： グリッドベースの画面ではない時


*例：グリッドベースの画面の時にスタイルを当てる*
```CSS
@media (grid: 0) {
    /*任意のスタイルを記述する*/
}
```

#### `height`
ビューポートの高さに応じて判断できます

`height: 300px`： ビューポートの高さが300pxの時
`min-height: 300px`：ビューポートの高さが300px以上の時
`max-height: 300px`：ビューポートの高さが300px以下の時


*例：ビューポートの高さが300px以上の時にスタイルを当てる*
```CSS
@media (min-height: 300px) {
    /*任意のスタイルを記述する*/
}
```

#### `hover`
第一の入力デバイスが要素の上でホバーすることができるかどうかに応じて判断できます。

`hover: none`： 入力デバイスがホバーできない時
`hover: hover`： 入力デバイスがホバーできる時 


*例：入力デバイスがホバーできる時にスタイルを当てる*
```CSS
@media (hover: hover) {
    /*任意のスタイルを記述する*/
}
```

#### `inverted-colors`
ブラウザーやOSが色を反転しているかどうかに応じて判断できます。
`inverted-colors: none`： 反転していない時
`inverted-colors: inverted`：反転している時


*例：反転している時にスタイルを当てる*
```CSS
@media (inverted-colors: inverted) {
    /*任意のスタイルを記述する*/
}
```

#### `monochrome`
出力デバイスのモノクロフレームバッファのピクセルあたりのビット数に応じて判断できます。
`monochrome`： モノクロデバイスの時
`min-monochrome: 8`：ビット数が8ビット以上の時
`max-monochrome: 8`：ビット数が8ビット以下の時


*例：ビット数が8ビット以上の時にスタイルを当てる*
```CSS
@media (min-monochrome: 8) {
    /*任意のスタイルを記述する*/
}
```

#### `orientation`
ビューポートの向きに応じて判断できます。
`orientation: portrait`：ビューポートは縦長の時
`orientation: landscape`：ビューポートは横長の時


*例：ビューポートは横長の時にスタイルを当てる*
```CSS
@media (orientation: landscape) {
    /*任意のスタイルを記述する*/
}
```

#### `overflow-block`
ブロック軸方向にあふれたコンテンツをどう扱うデバイスかに応じて判断できます。
`overflow-block: none`： 表示されないの時
`overflow-block: scroll`： スクロールで表示されるの時
`overflow-block: optional-paged`： スクロールできるが、ページで分かれているの時
`overflow-block: paged`： ページで分かれているの時


*例：スクロールで表示されるの時にスタイルを当てる*
```CSS
@media (overflow-block: scroll) {
    /*任意のスタイルを記述する*/
}
```

#### `overflow-inline`
インライン軸方向にあふれたコンテンツをどう扱うデバイスかに応じて判断できます。
`overflow-inline: none`： 表示されないの時
`overflow-inline: scroll`： スクロールで表示されるの時


*例：スクロールで表示されるの時にスタイルを当てる*
```CSS
@media (overflow-inline: scroll) {
    /*任意のスタイルを記述する*/
}
```

#### `pointer`
ポインティングデバイスであるかで判断できます。
マウスやタッチパネル、ペンタブレット、タッチパッド、トラックボール、ジョイスティックなど..

`pointer: none`：利用できるポインティングデバイスがない
`pointer: coarse`：正確性が低いポインティングデバイス。高いタップスクリーンなど
　　*※正確性が高いいポインティングデバイスも含む*
`pointer: fine`：正確性が高いポインティングデバイス。マウスなど

*例：正確性が低いポインティングデバイスの時にスタイルを当てる*
```CSS
@media (pointer: coarse) {
    /*任意のスタイルを記述する*/
}
```

#### `prefers-color-scheme`
ユーザーがシステムに要求したカラーテーマが明るさに応じて判断できます。
`prefers-color-scheme: light`： 明色のカラーテーマの時
`prefers-color-scheme: dark`： 暗い色のカラーテーマの時

*例：暗い色のカラーテーマの時にスタイルを当てる*
```CSS
@media (prefers-color-scheme: dark) {
    /*任意のスタイルを記述する*/
}
```

#### `prefers-contrast`
ユーザーがウェブコンテンツをより高い (またはより低い) コントラストで表示しているかに応じて判断できます。
`prefers-contrast: no-preference`：ユーザーが設定していない時
`prefers-contrast: more`：ユーザーが、より高いコントラストの時
`prefers-contrast: less`：ユーザーが、より低いコントラストの時

*例：ユーザーが、より高いコントラストの時にスタイルを当てる*
```CSS
@media (prefers-contrast: more) {
    /*任意のスタイルを記述する*/
}
```

#### `prefers-reduced-motion`
ユーザーが余計な動きを最少化しているかに応じて判断できます。
`prefers-reduced-motion: no-preference`：最少化していない時
`prefers-reduced-motion: reduce`：最少化している時


*例：最少化している時にスタイルを当てる*
```CSS
@media (prefers-reduced-motion: reduce) {
    /*任意のスタイルを記述する*/
}
```

#### `resolution`
出力デバイスのピクセル解像度に応じて判断できます。
`resolution: 150dpi`：出力デバイスのピクセル解像度が150dpiの時
`min-resolution: 150dpi`：出力デバイスのピクセル解像度が150dpi以上の時
`max-resolution: 150dpi`：出力デバイスのピクセル解像度が150dpi以下の時

*例：出力デバイスのピクセル解像度が150dpi以上の時にスタイルを当てる*
```CSS
@media (min-resolution: 150dpi) {
    /*任意のスタイルを記述する*/
}
```

#### `scripting`
スクリプトが利用できるかどうかに応じて判断できます。
`scripting: none`： スクリプトが利用できない時
`scripting: initial-only`： ページを読み込んでいる時
`scripting: enabled`：スクリプトに対応している時


*例：ページを読み込んでいる時にスタイルを当てる*
```CSS
@media (scripting: initial-only) {
    /*任意のスタイルを記述する*/
}
```

#### `update`
出力デバイスがどれだけの頻度でコンテンツの表示を更新することができるかに応じて判断できます。
`update: none`：更新されることはない時
`update: slow`：すばやく表示・更新することできない時
`update: fast`：すばやく表示・更新することできる時


*例：すばやく表示・更新することできる時にスタイルを当てる*
```CSS
@media (update: fast) {
    /*任意のスタイルを記述する*/
}
```

#### `width`
ビューポートの幅に応じて判断できます

`width: 300px`： ビューポートの幅が300pxの時
`min-width: 300px`：ビューポートの幅が300px以上の時
`max-width: 300px`：ビューポートの幅が300px以下の時


*例：ビューポートの幅が300px以上の時にスタイルを当てる*
```CSS
@media (min-width: 300px) {
    /*任意のスタイルを記述する*/
}
```



## 実用的なメディアクエリの活用方法
### ① スマホなどのタッチスクリーンデバイスの場合
タッチスクリーンのデバイスとマウス操作のデバイスでは、クリック・タップ範囲が違います。
他にも、タッチスクリーンのデバイスでは`:hover` によって、スタイルが崩れたりと挙動が変わる部分も多いです。
そんな時に、このメディアクエリを使いましょう。

```CSS
@media (hover: none) and (pointer: coarse){
  /*任意のスタイルを記述する*/
}
```

### ② デバイスがダークモード設定だった場合
近年ダークモードが普及し、ユーザーから「ダークモードが欲しい」と要望をいただくことが増えてきました。
そんな中で、システムのカラーモードに合わせて、色を変えたい時にこのメディアクエリを使いましょう。
```CSS
@media (prefers-color-scheme:dark) {
  /*ダークモードの場合の任意のスタイルを記述する*/
}

@media (prefers-color-scheme:light) {
  /*ライトモードの場合の任意のスタイルを記述する*/
}
```


### ③ システムのアニメーション効果や視覚効果設定が無効化されていた場合。
W3Cの`達成基準 2.3.3 インタラクションによるアニメーション`によると、
機能又は伝達されている情報に必要不可欠でない限り、インタラクションによって引き起こされるモーションアニメーションを無効にできるようにしないといけません。

また、画面上の視覚効果やアニメーション効果によってめまいなどが起きるため、視覚効果を無効にしている方がいます。
そういったケースへの配慮としてCSSの視覚効果を調整する場合は、こちらのメディアクエリを利用すると便利です。

```CSS
@media (prefers-reduced-motion: reduce) {
  /*任意のスタイルを記述する*/
}
```

## まとめ
この記事では、メディアクエリについての基本的な使い方についてまとめました。

普段、メディアクエリでは、`min-width`や`max-widht`などしか使わず、
こんなにいろんな条件でスタイルを分けたりすることができることに驚きました。

webサイトを開発する中で、ダークモードに対応したり、アクセシビリティを担保したり、色々な場合でメディアクエリは使えます。
まだ、サポートされていないものも紹介しましたが、ぜひ覚えて、自由に使えるようにしたいですね。

---

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

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

https://twitter.com/degudegu2510