如何解决呈现为黑色方块的动画元素(Chrome 错误)?
How to work around animated element rendered as a black square (Chrome bug)?
Chromium 版本 75.0.3770.100(官方构建)Arch Linux(64 位)。
在 Brave 的 Android 上也观察到(也基于 Chromium 75)。
我正在制作一个填充有白色渐变的旋转正方形:
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
backface-visibility: hidden;
}
@keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
<div class="spinning"></div>
这在 Firefox 上运行良好。但是,在 Chrome 上,我最初看到的是 黑色 正方形而不是白色正方形。就好像 Chrome 忘记渲染元素的图层一样。此外,旋转轴略微偏离中心。当我右击方块并选择"Inspect"时,它突然意识到它的方式错误并变成白色。
看起来我 运行 进入了 issue 966019,它出现在 Chrome 75 或可能是 74 并且已经确认和分配,但尚未修复。
值得注意的是:
- A
background-color
除了之外,background-image
使正方形变成那种颜色而不是黑色。
- 如果我在 div 中放置一些文本,我会得到一个不可见的正方形,而不是黑色的。
解决方法:
backface-visibility: visible
不会发生这种情况。但我需要隐藏它,因为我实际情况中的正方形有两个不同颜色的边,由两个这样的旋转正方形产生 180 度异相。
- 普通
background-color
而不是 渐变不会发生这种情况。但需要渐变以适应其余样式。
- 如果我从
0deg
开始轮换并经过 360deg
就不会发生这种情况。但随后它将与 "front" 方同时开始。
由于所有这些都有不良副作用,我正在寻找更好的解决方法。
另一种解决方法是在元素的 pseudo-element content
属性:
上触发动画
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
backface-visibility: hidden;
animation-fill-mode: forwards;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
.spinning::after {
content: "";
animation: trigger-paint .1s forwards 1;
}
@keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
@keyframes trigger-paint {
0% {content: ""}
100% {content: none}
}
<div class="spinning"></div>
但由于这里的技巧是强制重绘,我担心这会带来巨大的性能影响(根据我的开发工具,它确实会重新启动动画很多次,即使它已设置为开始一次)。
最终通过不依赖 backface-visibility
而是自己制作动画 visibility
解决了这个问题:
.spinning {
animation-name: spinning, hide-backface;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear, step-start;
width: 100px;
height: 100px;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
@keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
@keyframes hide-backface {
0% { visibility: hidden; }
25% { visibility: hidden; }
75% { visibility: visible; }
100% { visibility: hidden; }
}
<div class="spinning"></div>
另一种解决方案是考虑使用伪元素来创建两侧,这样就不会出现错误,并且可以轻松地单独管理每一侧。
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
position: relative;
transform-style:preserve-3d;
}
.spinning:before,
.spinning:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
backface-visibility: hidden;
}
.spinning:before {
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
.spinning:after {
transform: rotateY(180deg);
background:rgba(255,0,0,0.5);
}
@keyframes spinning {
0% {
transform: rotate3d(1, -1, 0, -180deg);
}
100% {
transform: rotate3d(1, -1, 0, 180deg);
}
}
<div class="spinning"></div>
Chromium 版本 75.0.3770.100(官方构建)Arch Linux(64 位)。
在 Brave 的 Android 上也观察到(也基于 Chromium 75)。
我正在制作一个填充有白色渐变的旋转正方形:
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
backface-visibility: hidden;
}
@keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
<div class="spinning"></div>
这在 Firefox 上运行良好。但是,在 Chrome 上,我最初看到的是 黑色 正方形而不是白色正方形。就好像 Chrome 忘记渲染元素的图层一样。此外,旋转轴略微偏离中心。当我右击方块并选择"Inspect"时,它突然意识到它的方式错误并变成白色。
看起来我 运行 进入了 issue 966019,它出现在 Chrome 75 或可能是 74 并且已经确认和分配,但尚未修复。
值得注意的是:
- A
background-color
除了之外,background-image
使正方形变成那种颜色而不是黑色。 - 如果我在 div 中放置一些文本,我会得到一个不可见的正方形,而不是黑色的。
解决方法:
backface-visibility: visible
不会发生这种情况。但我需要隐藏它,因为我实际情况中的正方形有两个不同颜色的边,由两个这样的旋转正方形产生 180 度异相。- 普通
background-color
而不是 渐变不会发生这种情况。但需要渐变以适应其余样式。 - 如果我从
0deg
开始轮换并经过360deg
就不会发生这种情况。但随后它将与 "front" 方同时开始。
由于所有这些都有不良副作用,我正在寻找更好的解决方法。
另一种解决方法是在元素的 pseudo-element content
属性:
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
backface-visibility: hidden;
animation-fill-mode: forwards;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
.spinning::after {
content: "";
animation: trigger-paint .1s forwards 1;
}
@keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
@keyframes trigger-paint {
0% {content: ""}
100% {content: none}
}
<div class="spinning"></div>
但由于这里的技巧是强制重绘,我担心这会带来巨大的性能影响(根据我的开发工具,它确实会重新启动动画很多次,即使它已设置为开始一次)。
最终通过不依赖 backface-visibility
而是自己制作动画 visibility
解决了这个问题:
.spinning {
animation-name: spinning, hide-backface;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear, step-start;
width: 100px;
height: 100px;
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
@keyframes spinning {
0% { transform: rotate3d(1, -1, 0, -180deg); }
100% { transform: rotate3d(1, -1, 0, 180deg); }
}
@keyframes hide-backface {
0% { visibility: hidden; }
25% { visibility: hidden; }
75% { visibility: visible; }
100% { visibility: hidden; }
}
<div class="spinning"></div>
另一种解决方案是考虑使用伪元素来创建两侧,这样就不会出现错误,并且可以轻松地单独管理每一侧。
.spinning {
animation-name: spinning;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
width: 100px;
height: 100px;
position: relative;
transform-style:preserve-3d;
}
.spinning:before,
.spinning:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
backface-visibility: hidden;
}
.spinning:before {
background-image: radial-gradient(farthest-corner at 40% 40%, #fff, #f7f7f7 50%, #e8e8e8 75%, #d1d1d1 100%);
}
.spinning:after {
transform: rotateY(180deg);
background:rgba(255,0,0,0.5);
}
@keyframes spinning {
0% {
transform: rotate3d(1, -1, 0, -180deg);
}
100% {
transform: rotate3d(1, -1, 0, 180deg);
}
}
<div class="spinning"></div>