HTML + CSS 无限滚动背景:在 Safari 上重复闪烁
HTML + CSS infinite scrolling background: Flicker on Safari at repeat
我正在创建一个带有一堆滚动层(前景、中景、背景等...)的场景,但令人恼火的是,当动画重新启动时,我在 Safari (14.0.3) 上出现了闪烁。 Chrome 或 Firefox 不会出现这种情况。
我在这里创建了一个最小的可重现示例:
https://brendon.github.io/safari_flicker/index.html
代码如下:
.animation {
position: relative;
height: 395px;
background-image: linear-gradient(#1b9dd9, #00b6ed 44%, #ffe56c 75%);
}
.animation .scrollingAnimation {
position: absolute;
overflow: hidden;
height: 100%;
width: 100%;
}
.animation .scrollingAnimation:before {
content: "";
position: absolute;
height: 100%;
width: 200%;
}
.animation .foreground:before {
/* Dimensions: */
/* width: 1696px; */
/* height: 74px; */
min-width: 6784px;
background-image: url("https://brendon.github.io/safari_flicker/foreground.png");
background-position: left bottom -11px;
background-repeat: repeat-x;
background-size: auto 74px;
transform: translateX(-1696px);
animation: foreground 10s linear infinite;
}
@keyframes foreground {
0% {
transform: translateX(-1696px);
}
to {
transform: translateX(-3392px);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="animation">
<div class="foreground scrollingAnimation"></div>
</div>
</body>
</html>
这是该问题的视频:
https://github.com/brendon/safari_flicker/raw/main/flicker_video.mp4
我已经尝试了很多方法来解决这个问题。它似乎有时会消失,具体取决于 window 宽度,但我正在寻找一个可靠的解决方案 :D
iOS Safari 也存在此问题。
我应该提一下,我不想为 background-position
属性 设置动画,因为这会导致性能问题并且不会被 GPU 加速。
您是否考虑过使用具有相同图像和动画的 2 个元素,并通过 -duration / 2
偏移 - 使用延迟 - 第一个元素动画?
想法是屏幕上始终有其中之一,任何渲染延迟都不应该可见。
见下文,我正在为两个伪元素设置动画。
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.animation, .foreground {
height: 100%;
width: 100%;
background: black;
}
.foreground:before, .foreground:after {
height: 100%;
width: 200%;
position: absolute;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 50vmin;
}
.foreground {
position: relative;
overflow-x: hidden;
}
.foreground:before {
content: 'A';
background: red;
animation: 10s linear -5s infinite foreground;
}
.foreground:after {
content: 'B';
background: blue;
animation: 10s linear 0s infinite foreground;
}
@keyframes foreground {
0% {
transform: translateX(100%);
}
to {
transform: translateX(-100%);
}
}
<div class="animation">
<div class="foreground scrollingAnimation"></div>
</div>
我最终使用 GSAP fromTo()
来管理过渡工作,而不是依赖 CSS 动画:
<div class="foreground scrollingAnimation"><div></div></div>
gsap.fromTo(
'.foreground > div',
{ xPercent: -25 },
{ xPercent: -50, duration: 10, repeat: -1, ease: 'none' }
)
.scrollingAnimation {
position: absolute;
overflow: hidden;
height: 100%;
width: 100%;
> div {
position: absolute;
height: 100%;
}
}
.foreground {
> div {
width: calc(1696px * 4);
background: {
image: url("https://brendon.github.io/safari_flicker/foreground.png");
position: left bottom;
repeat: repeat-x;
size: auto 74px;
}
}
}
它在非常宽的屏幕上会崩溃,但实际上,如果您在 6000 像素宽的屏幕上摇晃 window,祝您好运,先生。
GSAP 动画的方式是它在 requestAnimationFrame
期间通过 javascript 更改 translateX
值(我认为)所以它很好很流畅,并且闪烁问题没有在这种情况下存在。
我正在创建一个带有一堆滚动层(前景、中景、背景等...)的场景,但令人恼火的是,当动画重新启动时,我在 Safari (14.0.3) 上出现了闪烁。 Chrome 或 Firefox 不会出现这种情况。
我在这里创建了一个最小的可重现示例:
https://brendon.github.io/safari_flicker/index.html
代码如下:
.animation {
position: relative;
height: 395px;
background-image: linear-gradient(#1b9dd9, #00b6ed 44%, #ffe56c 75%);
}
.animation .scrollingAnimation {
position: absolute;
overflow: hidden;
height: 100%;
width: 100%;
}
.animation .scrollingAnimation:before {
content: "";
position: absolute;
height: 100%;
width: 200%;
}
.animation .foreground:before {
/* Dimensions: */
/* width: 1696px; */
/* height: 74px; */
min-width: 6784px;
background-image: url("https://brendon.github.io/safari_flicker/foreground.png");
background-position: left bottom -11px;
background-repeat: repeat-x;
background-size: auto 74px;
transform: translateX(-1696px);
animation: foreground 10s linear infinite;
}
@keyframes foreground {
0% {
transform: translateX(-1696px);
}
to {
transform: translateX(-3392px);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="animation">
<div class="foreground scrollingAnimation"></div>
</div>
</body>
</html>
这是该问题的视频:
https://github.com/brendon/safari_flicker/raw/main/flicker_video.mp4
我已经尝试了很多方法来解决这个问题。它似乎有时会消失,具体取决于 window 宽度,但我正在寻找一个可靠的解决方案 :D
iOS Safari 也存在此问题。
我应该提一下,我不想为 background-position
属性 设置动画,因为这会导致性能问题并且不会被 GPU 加速。
您是否考虑过使用具有相同图像和动画的 2 个元素,并通过 -duration / 2
偏移 - 使用延迟 - 第一个元素动画?
想法是屏幕上始终有其中之一,任何渲染延迟都不应该可见。
见下文,我正在为两个伪元素设置动画。
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.animation, .foreground {
height: 100%;
width: 100%;
background: black;
}
.foreground:before, .foreground:after {
height: 100%;
width: 200%;
position: absolute;
top: 0;
display: flex;
align-items: center;
justify-content: center;
font-size: 50vmin;
}
.foreground {
position: relative;
overflow-x: hidden;
}
.foreground:before {
content: 'A';
background: red;
animation: 10s linear -5s infinite foreground;
}
.foreground:after {
content: 'B';
background: blue;
animation: 10s linear 0s infinite foreground;
}
@keyframes foreground {
0% {
transform: translateX(100%);
}
to {
transform: translateX(-100%);
}
}
<div class="animation">
<div class="foreground scrollingAnimation"></div>
</div>
我最终使用 GSAP fromTo()
来管理过渡工作,而不是依赖 CSS 动画:
<div class="foreground scrollingAnimation"><div></div></div>
gsap.fromTo(
'.foreground > div',
{ xPercent: -25 },
{ xPercent: -50, duration: 10, repeat: -1, ease: 'none' }
)
.scrollingAnimation {
position: absolute;
overflow: hidden;
height: 100%;
width: 100%;
> div {
position: absolute;
height: 100%;
}
}
.foreground {
> div {
width: calc(1696px * 4);
background: {
image: url("https://brendon.github.io/safari_flicker/foreground.png");
position: left bottom;
repeat: repeat-x;
size: auto 74px;
}
}
}
它在非常宽的屏幕上会崩溃,但实际上,如果您在 6000 像素宽的屏幕上摇晃 window,祝您好运,先生。
GSAP 动画的方式是它在 requestAnimationFrame
期间通过 javascript 更改 translateX
值(我认为)所以它很好很流畅,并且闪烁问题没有在这种情况下存在。