当我引入 CSS 变量时,为什么浏览器会尝试使用其他无效的属性声明?

问题描述

我使用两个像这样的背景图像声明来获得回退:

background-image: url(https://via.placeholder.com/300x150.png?text=regular);
background-image: -webkit-image-set(
  url(https://via.placeholder.com/300x150.png?text=1x) 1x,url(https://via.placeholder.com/600x300.png?text=2x) 2x
);

JS 箱:https://jsbin.com/jadoharoyi/edit?html,output

这个想法是为了例如Firefox 显示“常规”bg,因为它不支持 -webkit-image-set,例如Chrome 显示“1x”或“2x”背景(取决于分辨率),因为它确实支持 -webkit-image-set。

到目前为止一切顺利。

但是如果我尝试通过 CSS 变量(对于 convoluted reasons)提供一个或多个图像 URL,它会失败:

--image-1x: url(https://via.placeholder.com/300x150.png?text=1x);

background-image: url(https://via.placeholder.com/300x150.png?text=regular);
background-image: -webkit-image-set(
  var(--image-1x) 1x,url(https://via.placeholder.com/600x300.png?text=2x) 2x
);

JS 箱:https://jsbin.com/vojiboqije/1/edit?html,output

现在,Firefox(macOS Big Sur 11.1 上的 85.0.2)根本不显示 bg 图像。据我所知,Firefox 突然很高兴尝试使用它不支持的第二个 background-image 声明。

但它在 Chrome (88.0.4324.146) 中运行良好。

我不明白为什么。有任何想法吗?这是一个错误吗?还是我的误解?

解决方法

这就是 CSS 变量的工作方式。当使用 CSS 变量时,浏览器只能在运行时评估该值,因此在我们评估该变量之前,该值将被视为有效(或假设处于待机模式),如果浏览器发现整个值无效,它将回退初始化或继承:

如果声明包含引用具有初始值的自定义属性的 var(),如上所述,或者 如果它使用有效的自定义属性,但属性值,替换其 var() 函数后,无效。 发生这种情况时,属性的计算值是属性的继承值或初始值,分别取决于该属性是否被继承,就像该属性的值已被指定为 unset 关键字。 ref

具有明显无效值的更明确的示例:

html {
  background:linear-gradient(red,blue); /* this will be used */
  background:strange-gradient(red,blue); /* this is a joke */
  
  min-height:100%;
}

当使用 CSS 变量时,不幸的是,第二个将被使用,使您的第一条指令无用。

html {
  --c:red;

  background:linear-gradient(red,blue);  /* this will be ignored */
  background:strange-gradient(var(--c),blue); /* the joke is being used ..*/
  
  min-height:100%;
}


这种行为在某种程度上是合乎逻辑的,因为通过更改变量,我们可以使值有效(如果以前无效)或无效(如果以前有效),因此浏览器应该考虑它。


对于您的特定情况,您可以考虑使用伪元素技巧:

.my-div {
  width: 300px;
  height: 150px;
  background-color: red;
  position:relative;
  z-index:0;
  
  --image-1x: url(https://via.placeholder.com/300x150.png?text=1x);

  background-image: url(https://via.placeholder.com/300x150.png?text=regular);
}
/* the pseudo element will cover the main background if it's valid */
.my-div::before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background-image: -webkit-image-set(
    var(--image-1x) 1x,url(https://via.placeholder.com/600x300.png?text=2x) 2x
  );
}
<div class="my-div">
</div>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...