问题描述
我使用两个像这样的背景图像声明来获得回退:
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>