CSSネイティブ変数がメディアクエリで機能しない


140

メディアクエリでCSS変数を使用しようとしていますが、機能しません。

:root {
  --mobile-breakpoint: 642px;
}

@media (max-width: var(--mobile-breakpoint)) {

}

いくつかのブラウザで試しましたか?(ChromeやFirefoxと同様)
Cohars

1
プリプロセッサなし@SandrinaPereira
Cohars

1
@SandrinaPereiraだから、FirefoxとChromeでできる
👍– Cohars


3
ただ、グーグルを介してこれを見つけるの人々のために明確にする:あなたができるメディアクエリーのスコープ内でCSSのカスタムプロパティを使用して、あなただけのメディアクエリ宣言でそれらを使用することはできません。
デビッドデプロスト

回答:


112

スペックから、

このvar()関数は、要素の任意のプロパティの値の任意の部分の代わりに使用できます。このvar()関数は、プロパティ名、セレクタ、またはプロパティ値以外のものとして使用できません。(これを行うと、通常は無効な構文が生成されるか、そうでなければ、変数に意味を持たない値が生成されます。)

そのため、メディアクエリでは使用できません。

そして、それは理にかなっています。--mobile-breakpointたとえば:root、に設定できるため、つまり、<html>要素であり、そこから他の要素に継承されます。ただし、メディアクエリは要素ではなく、から継承しないため、機能しません<html>

これは、CSS変数が達成しようとしていることではありません。代わりにCSSプリプロセッサを使用できます。


77
仕様はメディアクエリのCSS変数を現在処理していないという点で正解ですが、CSS変数が達成しようとしているのは正しくありません。CSS変数が作成された理由は、繰り返しとマジックナンバーを減らすことです
w3.org/TR/css-variables-1/#introを

69

以下のようオリオールが応答した、現在、CSS変数レベル1のは、var()メディアクエリで使用することはできません。ただし、この問題に対処する最近の開発がありました。数年後には、CSS環境変数モジュールレベル1が標準化および実装されると、env()最新のすべてのブラウザーのメディアクエリで変数を使用できるようになります。

仕様を読んで懸念がある場合、またはメディアクエリの使用例に対するサポートを表明したい場合は、GitHub w3c / csswg-drafts#1693または「[ css-env-1]」


元の回答2017-11-09:最近、CSSワーキンググループはCSS変数レベル2がを使用してユーザー定義の環境変数をサポートしenv()、それらをメディアクエリで有効にしようとすることを決定しましたAppleが最初に標準のユーザーエージェントプロパティを提案した後、2017年9月にiPhone Xが正式に発表される少し前に、グループはこの問題を解決しましWebKit:Timothy Hortonによる「Designing Websites for iPhone X」も参照)。他のブラウザ担当者は、テレビのディスプレイやにじみのあるインク印刷など、多くのデバイスで一般的に有用であることに同意しました。(env()以前は呼ばれていたconstant()が、現在は非推奨になっています。Peter-Paul Kochによるこの記事のように、古い名前を参照する記事が引き続き表示される場合があります。)数週間が経過した後、MozillaのCameron McCormackは、これらの環境変数がメディアクエリで使用できることに気付きTab Atkins、Jr.その後、Googleのユーザー、ユーザー定義の環境変数が、メディアクエリで使用できる上書き不可のグローバルルート変数として特に役立つことを認識しました。今度は、ディーン「ディノ」アップルジャクソンがレベル2の編集にAtkins加わります。

w3c/csswg-draftsGitHubの問題#1693で、この問題に関する最新情報を購読できます。(特に関連する履歴の詳細については、CSSWGミーティングボットの解像度に埋め込まれたミーティングログを展開し、「メディアクエリ」を表す「MQ」を検索してください。)

この問題は、今後さらに開発が行われたときに更新する予定です。未来はエキサイティングです。


2018-02-08の更新: Safari Technology Preview 49ではcalc()、メディアクエリでの解析のサポートが追加されました。これは、メディアクエリでのサポートの前置きとなる場合もありenv()ます。


2018年4月27日更新:GoogleのChromiumチームは、への取り組みを開始することを決定しましたenv()。これに対応して、Atkinsはenv()別の非公式のドラフト標準であるCSS環境変数モジュールレベル1を指定し始めました。(w3c / csswg-drafts#1693の彼のGitHubコメントw3c / csswg-drafts#1817の彼のコメントを参照してください。)ドラフトは、明示的なユースケースとしてメディアクエリの変数を呼び出しています。

環境変数は特定の要素から引き出されたものの値に依存しないため@mediavar()関数などが有効ではないルールなど、明確な要素が引き出されていない場所で使用できます。

仕様を読んで懸念がある場合、またはメディアクエリの使用例に対するサポートを表明したい場合は、GitHub w3c / csswg-drafts#1693または「[ css-env-1]”


アップデート2019-07-06:仕様に関する作業が継続されます。GitHubの問題#2627GitHubの問題#3578は、メディアクエリのカスタム環境変数に関するものです。


31

しかし、あなたができることは@media query:rootステートメントです!

:root {
     /* desktop vars */
}
@media screen and (max-width: 479px) {
    :root {
        /* mobile vars */
    }
}

Chrome、Firefox、およびEdgeで完全に動作します。この投稿の時点で少なくとも最新の製品バージョンです。


すごい!これは間違いなく正しい答えです。
SimplyComplexable

1
知ってよかった。1つの制限:その値にとしてアクセスする必要varがあるため、の他の場所の計算で使用できる場合cssでも、メディアクエリとvar宣言の2つの場所に「マジックバリュー」(ここでは479px)を配置する必要があります。
ToolmakerSteve

8

どうやら、そのようなネイティブCSS変数を使用することは不可能です。これは制限の1つです。

それを使用する賢い方法は、メディアクエリの変数を変更して、すべてのスタイルに影響を与えることです。この記事をお勧めします

:root {
  --gutter: 4px;
}

section {
  margin: var(--gutter);
}

@media (min-width: 600px) {
  :root {
    --gutter: 16px;
  }
}

「メディアクエリで変数を変更する」の意味がわかりません。例を示すことができますか?

1
これは私が意図したものではありません。メディアクエリの値について質問しました。

4
はい、ちょうどしました、それは私がリンクした記事にあります。私はそれがあなたが期待したものではないことを知っていますが、CSS変数はメディアクエリを定義するために使用することができません
Cohars '21

8

あなたが望むものを達成する1つの方法は、npmパッケージを使用することですpostcss-media-variables

npmパッケージの使用に問題がない場合は、こちらでドキュメントを確認できます。

/* input */
:root {
  --min-width: 1000px;
  --smallscreen: 480px;
}
@media (min-width: var(--min-width)) {}
@media (max-width: calc(var(--min-width) - 1px)) {}

@custom-media --small-device (max-width: var(--smallscreen));
@media (--small-device) {}

4
おかげで、私はプリプロセッサを使用しないようにしようとしました。

等 al:postcssでは、cssnext cssnext.io/features/#custom-media-queries
sebilasse

1
@sebilasse:custom-media-queriesは、css変数をメディアクエリのブレークポイントとして使用できないという主な問題に対処していません
zhirzh

1
postcssはプリプロセッサではありません

1

あなたは他の答えを読むことができるので、それを行うことはまだ不可能です。

誰かがカスタム環境変数に言及し(のenv()代わりにカスタムcss変数に似ていますvar())、原則は適切ですが、2つの主要な問題がまだあります。

  • ブラウザのサポートが弱い
  • これまでのところ、それらを定義する方法はありません(ただし、これはこれまでのところ非公式なドラフトにすぎないため、おそらく将来的になるでしょう)

1

短い答え

JavaScriptを使用してメディアクエリの値を変更し、css変数の値に設定できます。

// get value of css variable
getComputedStyle(document.documentElement).getPropertyValue('--mobile-breakpoint'); // '642px'

// search for media rule
var mediaRule = document.styleSheets[i].cssRules[j];

// update media rule
mediaRule.media.mediaText = '..'


長い答え

ページに含めることができる小さなスクリプトを書きました。それはの価値を持つすべてのメディアのルールを置き換える1pxCSS変数の値と--replace-media-1px、値を持つルール2pxを持つ--replace-media-2pxようにと。これは、メディアクエリのために働くwithmin-widthmax-widthheightmin-heightおよびmax-heightそれらが使用して接続している場合でもand

JavaScript:

function* visitCssRule(cssRule) {
    // visit imported stylesheet
    if (cssRule.type == cssRule.IMPORT_RULE)
        yield* visitStyleSheet(cssRule.styleSheet);

    // yield media rule
    if (cssRule.type == cssRule.MEDIA_RULE)
        yield cssRule;
}

function* visitStyleSheet(styleSheet) {
    try {
        // visit every rule in the stylesheet
        var cssRules = styleSheet.cssRules;
        for (var i = 0, cssRule; cssRule = cssRules[i]; i++)
            yield* visitCssRule(cssRule);
    } catch (ignored) {}
}

function* findAllMediaRules() {
    // visit all stylesheets
    var styleSheets = document.styleSheets;
    for (var i = 0, styleSheet; styleSheet = styleSheets[i]; i++)
        yield* visitStyleSheet(styleSheet);
}

// collect all media rules
const mediaRules = Array.from(findAllMediaRules());

// read replacement values
var style = getComputedStyle(document.documentElement);
var replacements = [];
for (var k = 1, value; value = style.getPropertyValue('--replace-media-' + k + 'px'); k++)
    replacements.push(value);

// update media rules
for (var i = 0, mediaRule; mediaRule = mediaRules[i]; i++) {
    for (var k = 0; k < replacements.length; k++) {
        var regex = RegExp('\\((width|min-width|max-width|height|min-height|max-height): ' + (k+1) + 'px\\)', 'g');
        var replacement = '($1: ' + replacements[k] + ')';
        mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
    }
}

CSS:

:root {
  --mobile-breakpoint: 642px;

  --replace-media-1px: var(--mobile-breakpoint);
  --replace-media-2px: ...;
}

@media (max-width: 1px) { /* replaced by 642px */
  ...
}

@media (max-width: 2px) {
  ...
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.