1272 文字
6 分

CSS Media Queryを使うときに気を付けること及び知見

2023-07-04

主にメディア特性が min-width または max-width である場合に限定して、利用する場合に気をつけた方が良いパターンや知見について紹介します。

同種のメディア特性では Media Query のネストを避ける#

そもそも Media Query をネストして書けることを知らない方が多いと思いますし、min-width や max-width 以外のメディア特性に慣れていない方が多いと思いますが、Media Query では画面幅だけでなくカラーや端末の種類や向きなど様々なメディア特定が利用でき、さらには論理演算子に加えてネストも許容されているなど、様々な記述が出来ます。

例えば次の記述は横長で、横幅が 300px 以上の端末にマッチします。

@media (min-width: 300px) and (orientation: landscape) {
/* ... */
}

これはネストを利用して次のようにも書けます。

@media (min-width: 300px) {
@media (orientation: landscape) {
/* ... */
}
}

また、カンマ区切りで指定すると OR になるため、次は横幅が 300px または横長の端末にマッチします。

@media (min-width: 300px), (orientation: landscape) {
/* ... */
}

これらの記述はとても便利ですが、一方で同種のメディア特性(min-width と max-width など)をネスト表記で指定してしまうと、適用範囲の可読性が著しく落ちる場合があります。

@media (max-width: 742px) {
@media (max-width: 1024px) {
/* ... */
}
@media (min-width: 1024px) {
/* ... */
}
}
/* ネストしたメディアクエリ内のルールセットの優先度は高くなるのか */
@media (max-width: 1024px) {
/* ... */
}

メディア特性 min-width と max-width の併用を避ける#

メディア特性 min-width と max-width を併用していると、後から記述されたものの方が優先度が高くなる CSS の性質や、min-width と max-width どちらも指定した値を含む範囲に適用される都合上、記述する順序によって適用される範囲が変わってしまうため、どちらかに制限した上で利用した方が可読性の高いコードになることが多いです。

いずれも極端な例ですが、次のようなケースが考えられます。

例:h1 と h2 の色が一致しない。

@media (min-width: 340px) {
h1 {
color: blue;
}
}
@media (max-width: 720px) {
h1 {
color: red;
}
}
@media (max-width: 720px) {
h2 {
color: red;
}
}
@media (min-width: 340px) {
h2 {
color: blue;
}
}

例:状態が 3 つ出来てしまう(red, 300px)→(blue, 300px)→(blue, 200px)

h1 {
color: red;
width: 200px;
}
@media (min-width: 340px) {
h1 {
color: blue;
}
}
@media (max-width: 340px) {
h1 {
width: 300px;
}
}

また min-width と max-width いずれかを利用するのに合わせて、値に応じてソートするルールを stylelint などで書けることを推奨します。CSS の優先度をまだあまり理解していない方の場合、後ろにあるメディアクエリで誤って上書きしてしまうということがよくある印象です。

例:h1 の色は 780px 以上でも青色になる

@media (min-width: 780px) {
h1 {
color: red;
}
}
@media (min-width: 340px) {
h1 {
color: blue;
}
}

例:h1 の色は 340px 以下でも青色になる

@media (max-width: 340px) {
h1 {
color: red;
}
}
@media (max-width: 780px) {
h1 {
color: blue;
}
}

メディア特性を min-width と max-width どちらを利用するかについては、モバイルとデスクトップどちらを優先して実装するかに合わせてやるとスムーズだと個人的には思います。

範囲の重複を避けるために not all を利用する#

Media Query では、not 演算子を利用して条件を反転できます。次の記述では、ルールセットが 340px 未満で適用されます。

@media not all and (min-width: 340px){
 /* ... */
}

これを利用すれば、min-width と max-width を利用する場合と異なり、範囲の重複を気にせず記述できるようになります。ですが、現在は Media Query Level 4 で追加された range 型を持った特性を利用した方が良いと思います。

Media Query Level 4 range 型を持ったメディア特性#

既にほとんどのモダンブラウザで利用できる Media Query Level 4 の機能を利用すれば、より柔軟性が高く可読性の良い記述が利用できます。Media Query Level 4 では range 型のメディア特性に加えて、or 演算子やメディア特性と値のペアに対して付けられる not なども追加されています。

例:720px 未満にマッチする

@media (width < 720px) {
/* ... */
}

例:340px より大きく 720px 以下の範囲でマッチする

@media (340px < width <= 720px) {
/* ... */
}

この記述であれば範囲を非常に認識しやすくなりますが、CSS の優先度などの問題は引き続き存在するため、記述する順序には気を付ける必要があります。

CSS Media Queryを使うときに気を付けること及び知見
https://blog.ohirunewani.com/posts/css-media-query-best-practices/
作者
hrdtbs
公開日
2023-07-04
ライセンス
CC BY-NC-SA 4.0