CSS 本机变量在媒体查询中不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40722882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 12:16:27  来源:igfitidea点击:

CSS native variables not working in media queries

cssmedia-queriescss-variables

提问by

I am trying to use CSS variables in media query and it does not work.

我试图在媒体查询中使用 CSS 变量,但它不起作用。

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

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

}

采纳答案by Oriol

From the spec,

规范来看,

The var()function can be used in place of any part of a value in any property on an element. The var()function can not be used as property names, selectors, or anything else besides property values. (Doing so usually produces invalid syntax, or else a value whose meaning has no connection to the variable.)

var()函数可用于代替元素上任何属性中值的任何部分。该var()函数不能用作属性名称、选择器或除属性值之外的任何其他内容。(这样做通常会产生无效的语法,或者其含义与变量没有联系的值。)

So no, you can't use it in a media query.

所以不,你不能在媒体查询中使用它。

And that makes sense. Because you can set --mobile-breakpointe.g. to :root, that is, the <html>element, and from there be inherited to other elements. But a media query is not an element, it does not inherit from <html>, so it can't work.

这是有道理的。因为你可以设置--mobile-breakpointeg 到:root,即<html>元素,并从那里继承到其他元素。但是媒体查询不是一个元素,它不继承自<html>,所以它不能工作。

This is not what CSS variables are trying to accomplish. You can use a CSS preprocessor instead.

这不是 CSS 变量想要完成的。您可以改用 CSS 预处理器。

回答by jschoi

As Oriol has answered, currently, CSS Variables Level?1's var()cannot be used in media queries. However, there have been recent developments that will address this problem. In a few years, once CSS Environment Variables Module Level?1is standardized and implemented, we'll be able to use env()variables in media queries in all modern browsers.

正如Oriol 所回答的,目前,CSS Variables Level?1'svar()不能用于媒体查询。然而,最近的发展将解决这个问题。几年后,一旦CSS Environment Variables Module Level?1标准化并实现,我们将能够env()在所有现代浏览器的媒体查询中使用变量。

If you read the specificationand have a concern, or if you want to voice your support for the media-query use case, you can still do so in GitHub w3c/csswg-drafts#1693or in any CSS GitHub issue prefixed with “[css-env-1]”.

如果您阅读规范并有疑问,或者如果您想表达您对媒体查询用例的支持,您仍然可以在GitHub w3c/csswg-drafts#1693任何以“[ css-env-1]”



Original answer 2017-11-09: Recently, the CSS Working Group decidedthat CSS Variables Level?2 will support user-defined environment variables using env(), and they will try to make them be valid in media queries. The Group resolved this after Apple first proposed standard user-agent properties, shortly before the official announcement of iPhone?X in September 2017 (see also WebKit: “Designing Websites for iPhone?X” by Timothy Horton). Other browser representatives then agreed they would be generally useful across many devices, such as television displays and ink printing with bleed edges. (env()used to be called constant(), but that has now been deprecated. You might still see articles that refer to the old name, such as this article by Peter-Paul Koch.) After some weeks passed, Cameron McCormack of Mozilla realizedthat these environment variables would be usable in media queries, and Tab Atkins, Jr. of Google then realizedthat user-defined environment variables would be especially useful as global, non-overridable root variables usable in media queries. Now, Dean “Dino” Hymanson of Apple will join Atkinsin editing Level?2.

原来的答复2017年11月9日:近日,CSS工作组决定CSS变量2级将使用支持用户自定义的环境变量?env(),他们会尽量让他们在媒体查询有效在 Apple于 2017 年 9 月正式发布 iPhone?X 之前不久,Apple 首次提出标准用户代理属性后,工作组解决了这个问题(另请参阅WebKit:“为 iPhone?X 设计网站”,Timothy Horton 着)。其他浏览器代表随后同意,它们通常可用于许多设备,例如电视显示器和带有出血边缘的墨水打印。(env()曾经被称为constant(),但现在已被弃用。您可能仍会看到引用旧名称的文章,例如Peter-Paul Koch 撰写的这篇文章。)几周后,Mozilla 的 Cameron McCormack 意识到这些环境变量可用于媒体查询,而Tab Atkins, Jr.之后,Google 意识到用户定义的环境变量作为可在媒体查询中使用的全局、不可覆盖的根变量特别有用。现在,Apple 的 Dean “Dino” Hymanson 将与 Atkins一起编辑 Level?2。

You can subscribe to updates on this matter in w3c/csswg-draftsGitHub issue?#1693. (For especially relevant historical details, expand the meeting logs embedded in the CSSWG Meeting?Bot's resolutionsand search for “MQ”, which stands for “media queries”.)

您可以在w3c/csswg-draftsGitHub issue?#1693订阅关于此事的更新。(对于特别相关的历史细节,请展开嵌入在CSSWG Meeting?Bot 决议中的会议日志并搜索“MQ”,代表“媒体查询”。)

I plan to update this question in the future when more developments occur. The future is exciting.

我计划在未来发生更多发展时更新这个问题。未来令人兴奋。



Update 2018-02-08: Safari Technology Preview?49has added support for parsing calc()in media queries, which may be a prelude to supporting env()in them as well.

2018 年 2 月 8 日更新: Safari Technology Preview?49添加了calc()对媒体查询解析的支持,这可能也是支持媒体查询的前奏env()



Update 2018-04-27: The Chromium team at Google has decided to start working on env(). In response, Atkins has started to specify env()in a separate, unofficial draft standard: the CSS Environment Variables Module Level?1. (See his GitHub comment in w3c/csswg-drafts#1693and his comment in w3c/csswg-drafts#1817.) The draft calls out variables in media queries as an explicit use case:

2018 年 4 月 27 日更新:Google 的 Chromium 团队决定开始研究env(). 作为回应,阿特金斯已经开始env()在一个单独的、非官方的草案标准中指定:CSS 环境变量模块级别?1。(参见他在 w3c/csswg-drafts#1693 中的 GitHub 评论他在 w3c/csswg-drafts#1817 中的评论。)草案将媒体查询中的变量作为一个显式用例:

Because environment variables don't depend on the value of anything drawn from a particular element, they can be used in places where there is no obvious element to draw from, such as in @mediarules, where the var()function would not be valid.

因为环境变量不依赖于从特定元素中抽取的任何值,所以它们可以用于没有明显元素可供抽取的地方,例如在@media规则中,var()函数无效的地方。

If you read the specification and have a concern, or if you want to voice your support for the media-query use case, you can still do so in GitHub w3c/csswg-drafts#1693or in any CSS GitHub issue prefixed with “[css-env-1]”.

如果您阅读规范并有疑虑,或者如果您想表达您对媒体查询用例的支持,您仍然可以在GitHub w3c/csswg-drafts#1693任何以“[ css-env-1]”



Update 2019-07-06: Work continues on the specifications. GitHub issue #2627and GitHub issue #3578are devoted to custom environmental variables in media queries.

2019 年 7月 6 日更新:规范的工作仍在继续。GitHub 问题 #2627GitHub 问题 #3578专门用于媒体查询中的自定义环境变量。

回答by Sean

What you CAN do however is @media query your :root statement!

但是,您可以做的是@media 查询您的 :root 语句!

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

Totally works in Chrome, Firefox and Edge at least the latest production versions as of this posting.

至少在本文发布时的最新生产版本中完全适用于 Chrome、Firefox 和 Edge。

回答by pradeep1991singh

One way to achieve what you want is using npm package postcss-media-variables.

实现您想要的一种方法是使用 npm package postcss-media-variables

If you are fine with using npm packages then you can take a look documentatoin for same here

如果您可以使用 npm 包,那么您可以在此处查看相同的文档

Example

例子

/* 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) {}

回答by Cohars

Apparently it's just not possible to use native CSS variables like that. It's one of the limitations.

显然,像这样使用原生 CSS 变量是不可能的。这是限制之一

A clever way to use it is to change your variables in the media-query, to impact all your style. I recommend this article.

使用它的一个巧妙方法是更改​​媒体查询中的变量,以影响您的所有风格。我推荐这篇文章

:root {
  --gutter: 4px;
}

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

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

回答by Facundo Colombier

Since it won't work as Oriol mentioned, a great solution using SASS variables is the one answered here by Red:

由于它不会像Oriol 提到的那样工作,因此使用 SASS 变量的一个很好的解决方案是Red 在此处回答

$primary: #ffcc00;
$secondary: #4b4b4b;

:root{ 
  --data-color-primary: #{$primary}; 
  --data-color-secondary: #{$secondary}; 
}

回答by The Vojtisek

As you can read other answers, still not possibleto do so.

正如您可以阅读其他答案一样,仍然无法这样做。

Someone mentioned custom environmental variables (similar to custom css variables env()instead of var()), and the principle is sound, though there are still 2 major issues:

有人提到了自定义环境变量(类似于自定义css变量env()而不是var()),原理是合理的,不过还是有2个大问题:

  • weak browser support
  • so far there is no way to define them (but probably will be in the future, as this is so far only an unofficial draft)
  • 弱浏览器支持
  • 到目前为止还没有办法定义它们(但可能会在未来定义,因为到目前为止这只是一个非官方的草案)

回答by Ich_73

Short Answer

简答

You can use JavaScript to change the value of media queries and set it to the value of a css variable.

您可以使用 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 = '..'



Long Answer

长答案

I wrote a small script which you can include on your page. It replaces every media rule with a value of 1pxwith the value of the css variable --replace-media-1px, rules with value 2pxwith --replace-media-2pxand so on. This works for the media queries with, min-width, max-width, height, min-heightand max-heighteven when they are connected using and.

我写了一个小脚本,您可以将其包含在您的页面中。它将每个媒体规则的值替换1px为 css 变量的值--replace-media-1px,规则的值2px替换为 with--replace-media-2px等等。该方法适用于媒体查询withmin-widthmax-widthheightmin-heightmax-height即使他们使用连接and

JavaScript:

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 = '(: ' + replacements[k] + ')';
        mediaRule.media.mediaText = mediaRule.media.mediaText.replace(regex, replacement);
    }
}

CSS:

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) {
  ...
}