CSS本机变量不适用于媒体查询

时间:2016-11-21 14:47:04

标签: css media-queries css-variables

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

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

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

}

7 个答案:

答案 0 :(得分:64)

来自spec

  

可以使用var()函数代替值的任何部分   元素上的任何属性。 var()函数不能用作   属性名称,选择器或除属性值之外的任何其他内容。   (这样做通常会产生无效的语法,或者是一个值为   意义与变量无关。)

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

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

这不是CSS变量试图完成的。您可以使用CSS预处理器。

答案 1 :(得分:39)

目前为Oriol has answeredCSS Variables Level 1’s var() cannot be used in media queries。但是,最近的一些发展将解决这个问题。 在几年内,CSS Environment Variables Module Level 1标准化并实施后,我们就可以在所有现代浏览器中的媒体查询中使用env()变量。

如果您阅读specification并有疑虑,或者您想表达对媒体查询用例的支持,您仍然可以在GitHub w3c/csswg-drafts#1693或{{3}中执行此操作}。

原始答案 2017-11-09 : 最近,{strong> CSS变量等级2 any CSS GitHub issue prefixed with “[css-env-1]”将使用env()支持用户定义的环境变量,并且他们会尝试使它们在媒体查询中有效。在2017年9月正式发布iPhone X之前不久,该集团解决了这个问题CSS Working Group decided(另见after Apple first proposed standard user-agent properties)。其他浏览器代表随后同意它们通常可用于许多设备,例如电视显示器和带有出血边缘的墨水打印。 (env()过去曾被称为constant(),但现已弃用。您可能仍会看到引用旧名称的文章,例如WebKit: “Designing Websites for iPhone X” by Timothy Horton。)几周后,{ {3}}这些环境变量可用于媒体查询,this article by Peter-Paul Koch用户定义的环境变量作为媒体查询中可用的全局,不可覆盖的根变量特别有用。现在,Cameron McCormack of Mozilla realized正在编辑第2级。

您可以在Tab Atkins, Jr. of Google then realized订阅有关此问题的更新。 (有关特别相关的历史详细信息,请展开嵌入在Dean “Dino” Jackson of Apple will join Atkins中的会议日志,并搜索“MQ”,它代表“媒体查询”。)

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

更新 2018-02-08 w3c/csswg-drafts GitHub issue #1693已添加对在媒体查询中解析calc()的支持,这也可能是在其中支持env()的前奏。

更新 2018-04-27 : Google的Chromium团队决定开始致力env()。作为回应,Atkins已开始在单独的非官方草案标准中指定env() CSSWG Meeting Bot’s resolutions 。 (请参阅Safari Technology Preview 49CSS Environment Variables Module Level 1。)草案将媒体查询中的变量称为明确的用例:

  

因为环境变量不依赖于从特定元素中提取的任何内容的值,所以它们可以在没有明显元素可以绘制的地方使用,例如在@media规则中,{ {1}}函数无效。

如果您阅读规范并有疑虑,或者您想表达对媒体查询用例的支持,您仍然可以在his GitHub comment in w3c/csswg-drafts#1693his comment in w3c/csswg-drafts#1817中执行此操作。

答案 2 :(得分:5)

实现目标的一种方法是使用npm包postcss-media-variables

如果您使用npm包很好,那么您可以在这里看一下documentatoin

实施例

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

答案 3 :(得分:4)

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

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

到目前为止,该版本至少可以在Chrome,Firefox和Edge上正常使用。

答案 4 :(得分:3)

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

使用它的一种聪明方法是更改​​媒体查询中的变量,以影响您的所有风格。我推荐this article

:root {
  --gutter: 4px;
}

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

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

答案 5 :(得分:2)

简短答案

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


长答案

我写了一个小脚本,您可以将其包含在页面中。它使用css变量1px的值替换值为--replace-media-1px的每个媒体规则,将值2px替换为--replace-media-2px的规则,依此类推。这适用于媒体查询withmin-widthmax-widthheightmin-heightmax-height,即使它们使用{{1 }}。

JavaScript:

and

CSS:

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);
    }
}

答案 6 :(得分:1)

您可以阅读其他答案,但仍然不可能

有人提到自定义环境变量(类似于自定义css变量 env() 而不是var()),尽管有两个主要问题,但原理是合理的:< / p>

  • 对浏览器的支持不足
  • 到目前为止,尚无办法对其进行定义(但可能会在将来,因为到目前为止这只是一个非正式草案)