かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

CSS メディアクエリのブレイクポイントに CSS 変数は使えない

タイトルのままです。
CSS 変数はメディアクエリ (@media) のブレイクポイントの値には使うことができないようです。

CSS 変数をブレイクポイントにしても動作しない

:root {
  --breakpoint-md: 48em;
}

@media (min-width: var(--breakpoint-md)) {
    body {
        color: #F00;
    }
}

これは動作しない。 (window が 48em 以上になっても color: #F00; にはならない)

This may seem confusing at first. If our variables are available at the :root of the page, why can't a media query access them?

Well, it comes down to what the :root element actually means: the root element of the HTML document. But conceptually, media queries aren't attached to HTML elements at all. These declarations are processed while your CSS is being parsed, so it won't know to look to the :root and pull in the variable values.
cf. Want CSS variables in media query declarations? Try this!

メディアクエリは HTML 要素に紐付いている訳ではないので、 HTML の :root に紐付いている変数を参照することができないので、メディアクエリのブレイクポイントは CSS 変数を参照することができない。のが理由のようです。

As luck would have it, the W3C isn't happy about this limitation either. Their proposal for "environment" variables is at the earliest stage right now (phase 1 as of May 2021), but it seems to tackle this very issue!

環境変数という概念で提案段階ですがこの問題について取り組まれているようです
cf. CSS Environment Variables Module Level 1

メディアクエリのブレイクポイントに変数を使う方法

Scss の変数をマスターとして CSS 変数とメディアクエリのブレイクポイントで使い回す

// _breakpoints.scss
$breakpoints: (
  xs: 0,
  sm: 30em,
  md: 48em,
  lg: 62em,
  xl: 80em,
  2xl: 96em,
) !default;
// _variables.scss
@use "./breakpoints" as bp;
:root {
  --content-max: #{map-get(bp.$breakpoints, xl)};
  --breakpoint-md: #{map-get(bp.$breakpoints, md)};
}
@use "./breakpoints" as bp;

@media (min-width: map-get(bp.$breakpoints, md)) {
  body {
    color: #F00;
  }
}

Sass などの変数を使えば可能なので、現状ではこの辺りが現実的な落とし所かも…
CSS 変数がメディアクエリのブレイクポイントに使えないのは知らなかったので罠でした!

おわり


[参考]

今季は 水星の魔女 を観ています