メディアクエリでCSS変数を使用しようとしていますが、機能しません。
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
メディアクエリでCSS変数を使用しようとしていますが、機能しません。
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
回答:
スペックから、
この
var()
関数は、要素の任意のプロパティの値の任意の部分の代わりに使用できます。このvar()
関数は、プロパティ名、セレクタ、またはプロパティ値以外のものとして使用できません。(これを行うと、通常は無効な構文が生成されるか、そうでなければ、変数に意味を持たない値が生成されます。)
そのため、メディアクエリでは使用できません。
そして、それは理にかなっています。--mobile-breakpoint
たとえば:root
、に設定できるため、つまり、<html>
要素であり、そこから他の要素に継承されます。ただし、メディアクエリは要素ではなく、から継承しないため、機能しません<html>
。
これは、CSS変数が達成しようとしていることではありません。代わりにCSSプリプロセッサを使用できます。
以下のようオリオールが応答した、現在、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-drafts
GitHubの問題#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の彼のコメントを参照してください。)ドラフトは、明示的なユースケースとしてメディアクエリの変数を呼び出しています。
環境変数は特定の要素から引き出されたものの値に依存しないため
@media
、var()
関数などが有効ではないルールなど、明確な要素が引き出されていない場所で使用できます。
仕様を読んで懸念がある場合、またはメディアクエリの使用例に対するサポートを表明したい場合は、GitHub w3c / csswg-drafts#1693または「[ css-env-1]”。
アップデート2019-07-06:仕様に関する作業が継続されます。GitHubの問題#2627とGitHubの問題#3578は、メディアクエリのカスタム環境変数に関するものです。
しかし、あなたができることは@media query:rootステートメントです!
:root {
/* desktop vars */
}
@media screen and (max-width: 479px) {
:root {
/* mobile vars */
}
}
Chrome、Firefox、およびEdgeで完全に動作します。この投稿の時点で少なくとも最新の製品バージョンです。
var
があるため、の他の場所の計算で使用できる場合css
でも、メディアクエリとvar宣言の2つの場所に「マジックバリュー」(ここでは479px)を配置する必要があります。
どうやら、そのようなネイティブCSS変数を使用することは不可能です。これは制限の1つです。
それを使用する賢い方法は、メディアクエリの変数を変更して、すべてのスタイルに影響を与えることです。この記事をお勧めします。
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
あなたが望むものを達成する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) {}
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 = '..'
ページに含めることができる小さなスクリプトを書きました。それはの価値を持つすべてのメディアのルールを置き換える1px
CSS変数の値と--replace-media-1px
、値を持つルール2px
を持つ--replace-media-2px
ようにと。これは、メディアクエリのために働くwith
、min-width
、max-width
、height
、min-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) {
...
}