我正在尝试在媒体查询中使用CSS变量,但它不起作用。
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
我正在尝试在媒体查询中使用CSS变量,但它不起作用。
:root {
--mobile-breakpoint: 642px;
}
@media (max-width: var(--mobile-breakpoint)) {
}
Answers:
从规格,
该
var()
函数可以代替元素上任何属性中值的任何部分。该var()
函数不能用作属性名称,选择器或除属性值之外的其他任何东西。(这样做通常会产生无效的语法,否则会产生其含义与变量无关的值。)
所以不,您不能在媒体查询中使用它。
这是有道理的。因为您可以将--mobile-breakpoint
例如设置为:root
,即<html>
元素,然后从那里继承其他元素。但是媒体查询不是元素,它也不继承自<html>
,因此它无法工作。
这不是CSS变量要完成的任务。您可以改用CSS预处理器。
正如Oriol回答的那样,当前,CSS变量1级var()
不能用于媒体查询中。然而,最近的发展将解决这个问题。在短短几年内,一旦CSS环境变量模块1级标准化和实施,我们就可以使用env()
在所有现代浏览器变量媒体查询。
如果您已阅读规范并有疑问,或者想要表达对媒体查询用例的支持,则仍可以在GitHub w3c / csswg-drafts#1693或任何带有前缀“ [[ css-env-1]”。
原来的答复2017年11月9日:近日,CSS工作组决定是CSS变量2级将使用支持用户自定义的环境变量env()
,他们会尽量让他们在媒体查询有效。在苹果公司首次提出标准的用户代理属性之后,即2017年9月iPhone X正式发布前不久,该小组解决了这一问题(另见WebKit:“为iPhone X设计网站”)。然后,其他浏览器代表同意,它们通常可用于许多设备,例如电视显示器和带有出血边缘的墨水打印。(env()
以前称为constant()
,但现在已弃用。您可能仍然会看到引用旧名称的文章,例如Peter-Paul Koch的这篇文章。)经过了几周,Mozilla的Cameron McCormack意识到这些环境变量可以在媒体查询中使用,而Tab Atkins,Jr.则认为。然后,Google的作者意识到用户定义的环境变量作为可用于媒体查询的全局,不可替代的根变量特别有用。现在,苹果公司的Dean“ Dino” Jackson将与Atkins一起编辑Level 2。
您可以在w3c/csswg-drafts
GitHub第1693期中订阅有关此问题的更新。(有关特别相关的历史详细信息,请扩展嵌入CSSWG Meeting Bot决议中的会议日志,并搜索“ MQ”,代表“媒体查询”。)
我计划在将来出现更多发展时更新此问题。未来令人兴奋。
2018年2月8日更新:
Safari Technology Preview 49增加了calc()
对媒体查询中的解析的支持,这也可能是env()
对它们的支持的前奏。
2018年4月27日更新:Google的Chromium团队已决定开始进行开发env()
。作为回应,Atkins已经开始env()
在一个单独的非正式草案标准中指定:CSS Environment Variables Module Level 1。(见他的GitHub的评论在W3C / csswg-起草#1693,并在他的评论W3C / csswg-起草#1817。)在媒体查询作为一个明确的使用情况下的呼叫草案出来变量:
由于环境变量不依赖于从特定元素中抽取的任何东西的值,因此可以在没有明显元素可借鉴的地方(例如在
@media
规则中,var()
函数无效)使用它们。
如果您已阅读规范并有疑问,或者想要表达对媒体查询用例的支持,则仍可以在GitHub w3c / csswg-drafts#1693或任何带有前缀“ [[ css-env-1]”。
更新2019-07-06:规格方面的工作仍在继续。GitHub问题2627和GitHub问题3578专门用于媒体查询中的自定义环境变量。
但是,您可以做的是@media查询您的:root语句!
:root {
/* desktop vars */
}
@media screen and (max-width: 479px) {
:root {
/* mobile vars */
}
}
截至本文发布时,至少可以在Chrome,Firefox和Edge上完全运行。
var
,则可以在的其他位置进行计算时css
,这仍然需要将“魔术值”(此处为479px)放在两个位置:媒体查询和var声明。
显然,不可能像这样使用本机CSS变量。这是局限性之一。
一种聪明的使用方法是更改媒体查询中的变量,以影响所有样式。我推荐这篇文章。
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
实现您想要的一种方法是使用npm package 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) {
...
}