纯CSS3无限循环滑块

3
我想使用CSS3(以及稍后的Sass)制作不断移动的幻灯片。我有九个图像和一个宽度为850像素的蒙版div,我知道如何将第一个图像动画化,但我不知道如何计算其余图像的值。
我在Smashing Magazinehugogiraudel.com上找到了很好的教程,但这是静态状态,我不知道如何使其仍然移动。
如果有人能帮助我理解这一点以及如何使用SASS,则会非常好。
这里是我完成的CodePen。 以下是代码:

#slider {
  width: 850px;
  margin: 0 150px;
}
.ruler {
  display: flex;
  flex-flow: row nowrap;
  border: 1px solid black;
}
.u10 {
  flex: 1 1 0;
  width: 10%;
  text-align: center;
  z-index: 0;
}
.u10:nth-child(even) {
  background-color: white;
}
.u10:nth-child(odd) {
  background-color: gray;
}
ul {
  list-style: outside none none;
  position: relative;
  height: 100px;
}
ul:after {
  border: 1px solid black;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  content: "";
}
li {
  position: absolute;
}
.img1 {
  left: -120px;
}
.img2 {
  left: 0px;
}
.img3 {
  left: 120px;
}
.img4 {
  left: 240px;
}
.img5 {
  left: 360px;
}
.img6 {
  left: 480px;
}
.img7 {
  left: 600px;
}
.img8 {
  left: 720px;
}
.img9 {
  left: 840px;
}
.animation {
  animation: 10s linear 0s infinite running cycle1;
}
@keyframes cycle1 {
  0% {
    left: -120px;
    opacity: 0;
  }
  1% {
    left: -120px;
    opacity: 1;
  }
  99% {
    left: 840px;
    opacity: 1;
  }
  100% {
    left: -120px;
    opacity: 0;
  }
}
<div id="slider">
  <div class="ruler">
    <span class="u10">10%</span>
    <span class="u10">20%</span>
    <span class="u10">30%</span>
    <span class="u10">40%</span>
    <span class="u10">50%</span>
    <span class="u10">60%</span>
    <span class="u10">70%</span>
    <span class="u10">80%</span>
    <span class="u10">90%</span>
    <span class="u10">100%</span>
  </div>
  <ul>
    <li class="image-wrapper img1">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
  </ul>
  <ul>
    <li class="image-wrapper img1 animation">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>

  </ul>
</div>


将所有图像都包装起来,然后对该包装器进行动画处理,而不是一次只对一个图像进行处理,这样怎么样? - Luuuud
@LuudJacobs:这是一个选项,但是将包装器动画化而不是单个元素意味着动画应该保持到最后一个元素完全进入视图并消失。这将影响滑块的连续性质 - Harry
1个回答

6
为了制作一个不断移动的滑块动画,不要给每个图像元素分配不同的位置。相反,将它们定位在父元素外的同一位置,然后为每个图像元素逐渐不同的animation-delay赋值,就像下面的代码片段中一样。给每个图像元素不同的起始位置意味着它们每个都需要提供不同的持续时间,因为速度必须不同(因为从左到右必须覆盖的像素数量会很高)。
由于容器中总共有9个图像,在任何时候,每个单独的图像元素的延迟应该等于(animation-duration/9) * (n-1),其中n是元素的编号。为简单起见,我修改了animation-duration为9秒,因此第一个图像的animation-delay将是0秒,第二个图像的animation-delay将是1秒,以此类推。

#slider {
  width: 850px;
  margin: 0 150px;
}
.ruler {
  display: flex;
  flex-flow: row nowrap;
  border: 1px solid black;
}
.u10 {
  flex: 1 1 0;
  width: 10%;
  text-align: center;
  z-index: 0;
}
.u10:nth-child(even) {
  background-color: white;
}
.u10:nth-child(odd) {
  background-color: gray;
}
ul {
  list-style: outside none none;
  position: relative;
  height: 100px;
}
ul:after {
  border: 1px solid black;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  content: "";
}
li {
  position: absolute;
}
.img1 {
  left: -120px;
}
.img2 {
  left: 0px;
}
.img3 {
  left: 120px;
}
.img4 {
  left: 240px;
}
.img5 {
  left: 360px;
}
.img6 {
  left: 480px;
}
.img7 {
  left: 600px;
}
.img8 {
  left: 720px;
}
.img9 {
  left: 840px;
}
.animation {
  animation: 9s linear 0s infinite running cycle1;
}
@keyframes cycle1 {
  0% {
    left: -120px;
    opacity: 0;
  }
  1% {
    left: -120px;
    opacity: 1;
  }
  99% {
    left: 850px;
    opacity: 1;
  }
  100% {
    left: -120px;
    opacity: 0;
  }
}
.animation[class*='img'] {
  left: -120px;
}
.animation.img2 {
  animation-delay: 1s;
}
.animation.img3 {
  animation-delay: 2s;
}
.animation.img4 {
  animation-delay: 3s;
}
.animation.img5 {
  animation-delay: 4s;
}
.animation.img6 {
  animation-delay: 5s;
}
.animation.img7 {
  animation-delay: 6s;
}
.animation.img8 {
  animation-delay: 7s;
}
.animation.img9 {
  animation-delay: 8s;
}
ul.overflow-hidden {
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="slider">
  <div class="ruler">
    <span class="u10">10%</span>
    <span class="u10">20%</span>
    <span class="u10">30%</span>
    <span class="u10">40%</span>
    <span class="u10">50%</span>
    <span class="u10">60%</span>
    <span class="u10">70%</span>
    <span class="u10">80%</span>
    <span class="u10">90%</span>
    <span class="u10">100%</span>
  </div>
  <h3>Without animation</h3>
  <ul>
    <li class="image-wrapper img1">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
  </ul>
  <h3>With the portions outside the container visible</h3>
  <ul>
    <li class="image-wrapper img1 animation">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2 animation">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3 animation">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4 animation">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5 animation">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6 animation">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7 animation">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8 animation">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9 animation">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
  </ul>
  <h3>With the portions outside the container hidden</h3>
  <ul class='overflow-hidden'>
    <li class="image-wrapper img1 animation">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2 animation">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3 animation">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4 animation">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5 animation">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6 animation">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7 animation">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8 animation">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9 animation">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
  </ul>
</div>


如果你想让容器中的图片在一开始就可见(而不是一开始是一个空容器),那么如果不添加额外的元素,这将很难实现。你可以使用上面提到的相同方法,添加一个包含所有9个图像的额外虚拟包装器,并仅对其进行一次动画处理,以使其在真正的动画之前出现。下面的代码片段演示了这种方法的示例。

#slider {
  width: 850px;
  margin: 0 150px;
}
.ruler {
  display: flex;
  flex-flow: row nowrap;
  border: 1px solid black;
}
.u10 {
  flex: 1 1 0;
  width: 10%;
  text-align: center;
  z-index: 0;
}
.u10:nth-child(even) {
  background-color: white;
}
.u10:nth-child(odd) {
  background-color: gray;
}
ul {
  list-style: outside none none;
  position: relative;
  height: 100px;
  padding: 0px 0px;
}
ul:after {
  border: 1px solid black;
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  content: "";
}
li {
  position: absolute;
}
.img1 {
  left: -120px;
}
.img2 {
  left: 0px;
}
.img3 {
  left: 120px;
}
.img4 {
  left: 240px;
}
.img5 {
  left: 360px;
}
.img6 {
  left: 480px;
}
.img7 {
  left: 600px;
}
.img8 {
  left: 720px;
}
.img9 {
  left: 840px;
}
.animation {
  animation: 9s linear 5s infinite running cycle1; /* small delay added for image to be loaded, this can be ignored if image is preloaded */
}
@keyframes cycle1 {
  0% {
    left: -100px;
    opacity: 0;
  }
  0.01% {
    left: -100px;
    opacity: 1;
  }
  99.99% {
    left: 854px; /* total distance to be covered to be same as width of the dummy wrapper */
    opacity: 1;
  }
  100% {
    left: -100px;
    opacity: 0;
  }
}
.animation[class*='img'] {
  left: -100px;
}
.animation.img1 {
  animation-delay: 6s;
}
.animation.img2 {
  animation-delay: 7s;
}
.animation.img3 {
  animation-delay: 8s;
}
.animation.img4 {
  animation-delay: 9s;
}
.animation.img5 {
  animation-delay: 10s;
}
.animation.img6 {
  animation-delay: 11s;
}
.animation.img7 {
  animation-delay: 12s;
}
.animation.img8 {
  animation-delay: 13s;
}
ul.overflow-hidden {
  overflow: hidden;
}
.image-dummy {
  position: absolute;
  left: -100px;
  width: 954px; /* 100px image width + 6px imaee margin * no. of images */
  animation: 9s linear dummy-move 1 forwards 5s;
  white-space: nowrap;
  margin: 0px;
}
.image-dummy img {
  float: left;
  margin-right: 6px;
}
@keyframes dummy-move {
  from {
    left: -100px;
  }
  to {
    left: 866px; /* rough calculation equal to width of container * (margin-right * 2) */
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id="slider">
  <div class="ruler">
    <span class="u10">10%</span>
    <span class="u10">20%</span>
    <span class="u10">30%</span>
    <span class="u10">40%</span>
    <span class="u10">50%</span>
    <span class="u10">60%</span>
    <span class="u10">70%</span>
    <span class="u10">80%</span>
    <span class="u10">90%</span>
    <span class="u10">100%</span>
  </div>
  <h3>Without animation</h3>
  <ul>
    <li class="image-wrapper img1">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
  </ul>
  <h3>With the portions outside the container visible</h3>
  <ul>
    <li class="image-wrapper img1 animation">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2 animation">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3 animation">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4 animation">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5 animation">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6 animation">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7 animation">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8 animation">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9 animation">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
  </ul>
  <h3>With the portions outside the container hidden</h3>
  <ul class='overflow-hidden'>
    <li class="image-wrapper img1 animation">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
    <li class="image-wrapper img2 animation">
      <img src="http://placehold.it/100?text=2" alt="">
    </li>
    <li class="image-wrapper img3 animation">
      <img src="http://placehold.it/100?text=3" alt="">
    </li>
    <li class="image-wrapper img4 animation">
      <img src="http://placehold.it/100?text=4" alt="">
    </li>
    <li class="image-wrapper img5 animation">
      <img src="http://placehold.it/100?text=5" alt="">
    </li>
    <li class="image-wrapper img6 animation">
      <img src="http://placehold.it/100?text=6" alt="">
    </li>
    <li class="image-wrapper img7 animation">
      <img src="http://placehold.it/100?text=7" alt="">
    </li>
    <li class="image-wrapper img8 animation">
      <img src="http://placehold.it/100?text=8" alt="">
    </li>
    <li class="image-wrapper img9 animation">
      <img src="http://placehold.it/100?text=9" alt="">
    </li>
    <li class='image-dummy'>
      <img src="http://placehold.it/100?text=9" alt="">
      <img src="http://placehold.it/100?text=8" alt="">
      <img src="http://placehold.it/100?text=7" alt="">
      <img src="http://placehold.it/100?text=6" alt="">
      <img src="http://placehold.it/100?text=5" alt="">
      <img src="http://placehold.it/100?text=4" alt="">
      <img src="http://placehold.it/100?text=3" alt="">
      <img src="http://placehold.it/100?text=2" alt="">
      <img src="http://placehold.it/100?text=1" alt="">
    </li>
  </ul>
</div>

使用这种方法比适应你的方式更容易产生这种效果,因为你的方式需要9个不同的关键帧设置来产生所需的效果。


谢谢您的回复,@Harry。但是您的解决方案有一个问题,在开始时容器为空(不可接受)。您知道如何使用我的方法(使用不同的图像位置)来解决这个问题吗?或者在纯CSS中是否有现成的解决方案可以解决我的问题? - user19291
用你的方法,要实现(并保持)连续运动非常困难。我会尝试看看是否可以调整我的方法。 - Harry
@user19291:我已经调整了我的方法,以产生您所需的效果。请检查一下是否有帮助,如果有,请考虑将答案标记为已接受。 - Harry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接