当背景大小为 100% 时,如何使用百分比为背景位置设置动画?

How to animate background-position using percentages when background-size is 100%?

举个例子:

html {
    height: 100%;
}

body {
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: black;
    height: 100%;
    margin: 0;
}

#main {
    background: #222222;
    position: relative;
    flex: 640px 0 0;
    height: 360px;
}

@keyframes stars {
 0% {
        background-position: 0 0;
    }
 100% {
        background-position: -100% 0;
    }
}

#stars {
    animation: stars 10s linear infinite;
    background-image: url('https://i.imgur.com/nyFndCj.png');
    background-size: 100% 100%;
    background-repeat: repeat repeat;
    position: absolute;
    width: 100%;
    height: 100%;
}
<div id="main">
  <div id="stars"></div>
</div>

这里的想法是通过使用百分比更改背景位置来为星星从一侧移动到另一侧设置动画。例如,我可以使用 px 来完成这项工作,但这需要我提前知道宽度(在本例中为 640px),如果我想更改 width/height 14=] 我需要更改动画值,我想避免这种情况,因此更改百分比。另外,我只想用 CSS 来完成这个,根本不需要 JavaScript。

缩小背景尺寸并使用缩放通过增加容器尺寸来纠正此问题。然后你就可以随心所欲地设置背景动画了:

body {
  background-color: black;
  height: 100vh;
  margin: 0;
}

#main {
  background: #222222;
  position: relative;
  width: 100%;
  height: 360px;
  overflow: hidden;
}

#stars {
  animation: stars 10s linear infinite;
  background-image: url('https://i.imgur.com/nyFndCj.png');
  background-size: 50% 100%;
  position: absolute;
  left: 0;
  right: 0;
  height: 100%;
  transform: scaleX(2);
}

@keyframes stars {
  0% {
    background-position: left;
  }
  100% {
    background-position: right;
  }
}
<div id="main">
  <div id="stars"></div>
</div>

这是另一个没有比例的想法,您还可以使用 right:-100%left:-100%width:200%

将元素放大两倍

body {
  background-color: black;
  height: 100vh;
  margin: 0;
}

#main {
  background: #222222;
  position: relative;
  width: 100%;
  height: 360px;
  overflow: hidden;
}

#stars {
  animation: stars 10s linear infinite;
  background-image: url('https://i.imgur.com/nyFndCj.png');
  background-size: 50% 100%;
  position: absolute;
  left: 0;
  right: -100%;
  height: 100%;
}

@keyframes stars {
  0% {
    background-position: left;
  }
  100% {
    background-position: right;
  }
}
<div id="main">
  <div id="stars"></div>
</div>

这是另一个考虑到伪元素的简化:

body {
  background-color: black;
  height: 100vh;
  margin: 0;
}

#main {
  position: relative;
  width: 100%;
  height: 360px;
  overflow: hidden;
  z-index:0;
}
#main:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:-100%;
  bottom:0;
  animation: stars 10s linear infinite;
  background: 
    url('https://i.imgur.com/nyFndCj.png') left/50% 100%,
    #222222;
}

@keyframes stars {
  100% {
    background-position: right;
  }
}
<div id="main">
</div>

在所有情况下,诀窍是避免在 background-size 中包含 100% 100%,否则将无法使用百分比制作动画。


我使用 left/right 进行简化,相当于 0% 50%/100% 50%。只需在两者之间切换即可改变方向。

此处有更多详细信息:


并且由于我们已经将容器的尺寸变大了,我们还可以使用 translate 为它设置动画以获得更好的性能:

body {
  background-color: black;
  height: 100vh;
  margin: 0;
}

#main {
  position: relative;
  width: 100%;
  height: 360px;
  overflow: hidden;
  z-index:0;
}
#main:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:-100%;
  bottom:0;
  animation: stars 10s linear infinite;
  background: 
    url('https://i.imgur.com/nyFndCj.png') left/50% 100%,
    #222222;
}

@keyframes stars {
  100% {
    transform: translateX(-50%);
  }
}
<div id="main">
</div>

缩放:

body {
  background-color: black;
  height: 100vh;
  margin: 0;
}

#main {
  position: relative;
  width: 100%;
  height: 360px;
  overflow: hidden;
  z-index:0;
}
#main:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:0;
  bottom:0;
  transform:scaleX(2);
  transform-origin:left;
  animation: stars 10s linear infinite;
  background: 
    url('https://i.imgur.com/nyFndCj.png') left/50% 100%,
    #222222;
}

@keyframes stars {
  100% {
    transform:scaleX(2) translateX(-50%);
  }
}
<div id="main">
</div>

反方向

body {
  background-color: black;
  height: 100vh;
  margin: 0;
}

#main {
  position: relative;
  width: 100%;
  height: 360px;
  overflow: hidden;
  z-index:0;
}
#main:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:0;
  bottom:0;
  transform:scaleX(2);
  transform-origin:right;
  animation: stars 10s linear infinite;
  background: 
    url('https://i.imgur.com/nyFndCj.png') left/50% 100%,
    #222222;
}

@keyframes stars {
  100% {
    transform:scaleX(2) translateX(50%);
  }
}
<div id="main">
</div>