likes
comments
collection
share

自动轮播跑马灯💡,仅用CSS是否能?

作者站长头像
站长
· 阅读数 11

在最近开发✍️的需求中,要求实现类似「跑马灯💡」的效果。所谓「跑马灯💡」,我的理解就是能「自动播放」且「不能滑动」的「轮播图」。

需求

说起「轮播图」,相信大家脑海立马浮现的是「Swiper」。我也一样,很多「轮播图」需求都是用的「Swiper」。

先看效果 ⬇️ :

自动轮播跑马灯💡,仅用CSS是否能?

对于该效果而言,使用「Swiper」有两个缺点:

  1. 无法实现「无缝滚动」;
  2. 太「重」;

第一点,可以修改「Swiper」的swiper-wrapper动画的「三次贝塞尔曲线函数」为linear,理论上可以实现「无缝」,但实际上每个swiper-slide切换都会有轻微卡顿,效果不太理想(如果有更好的方法,欢迎👏在评论区留言)。

.swiper-wrapper {
    transition-timing-function: linear;
}

第二点,对于不用交互的自动轮播,使用「Swiper」有点臃肿。

所以,能不能仅用「CSS」来实现这个效果呢?

无缝滚动

跑马灯的结构是常见的「html列表」。

<html>
 <body> 
  <div class="scroll"> 
   <ul class="list"> 
    <li class="item">1</li> 
    <li class="item">2</li> 
    <li class="item">3</li> 
    <li class="item">4</li> 
    <li class="item">5</li> 
    <li class="item">6</li> 
    <li class="item">7</li> 
   </ul> 
  </div>  
  <style>
    body {
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .scroll {
      width: 400px;
      height: 100px;

      border: 1px solid red;
    }
    ul {
      display: flex;
    }
    li {
      width: 100px;
      height: 100px;

      flex-shrink: 0;

      box-sizing: border-box;

      border: 1px solid green;
    }
  </style> 
 </body>
</html>

此时,跑马灯呈现出来的效果 ⬇️ : 自动轮播跑马灯💡,仅用CSS是否能?

接下来,让ul标签动起来,添加animation横向偏移动画:

ul {
    display: flex;
    animation: scroll 5s linear infinite;
}

@keyframes scroll {
    0% {
        transform: translate(0px, 0px);
    }

    100% {
        transform: translate(-700px, 0px);
    }
}

因为每个li的宽度为100px,所以全部滚动一遍,需要在「X轴」负偏移 100px * 7 = 700px

跑马灯动态效果如下 ⬇️ :

自动轮播跑马灯💡,仅用CSS是否能?

很明显,还有两个问题:

  1. 超出部分不应该显示;
  2. 最后一个li后面存在空白;

第一个问题很简单,只需要在.scroll中添加overflow: hidden;

.scroll {
    width: 400px;
    height: 100px;
    overflow: hidden;
    border: 1px solid red;
}

自动轮播跑马灯💡,仅用CSS是否能?

解决第二个问题,需要在最后li添加「一屏显示数量」的li。对于上述Demo而言,「一屏数量」为400px / 100px = 4

<ul class="list"> 
    <li class="item">1</li> 
    <li class="item">2</li> 
    <li class="item">3</li> 
    <li class="item">4</li> 
    <li class="item">5</li> 
    <li class="item">6</li> 
    <li class="item">7</li> 
    
    <!-- 额外的li -->
    <li class="item">1</li> 
    <li class="item">2</li> 
    <li class="item">3</li> 
    <li class="item">4</li> 
</ul> 

自动轮播跑马灯💡,仅用CSS是否能?

这时有小伙伴可能会有疑惑:“我要滚动的数据是从接口拿回来的,数量不固定,要怎么处理?”。

这也很简单,可以使用「css变量」来处理。

<ul class="list" style="--count: 7"> 
    ...
</ul> 
ul {
    display: flex;
    animation: scroll calc(var(--count) * 1s) linear infinite;
}
@keyframes scroll {
    0% {
        transform: translate(0px, 0px);
    }
    100% {
        transform: translate(calc(-100px * var(--count)), 0px);
    }
}

配合像「Vue」这种框架,可以很容易把「列表的数量」传给--count,从而适配不同数量的li

有缝滚动

通过对上述Demo进行改造,也实现类似「Swiper」的自动轮播。

首先,使用css动画的steps()ul动画进行改写:

ul {
      display: flex;
      animation: scroll calc(var(--count) * 1s) steps(var(--count)) infinite;
}

区别在于,把「三次贝塞尔曲线函数」替换成steps(),实现逐帧动画。

此时,跑马灯的效果如下 ⬇️ :

自动轮播跑马灯💡,仅用CSS是否能?

初步效果已经有了,接下来为每一个li添加从右到左偏移的动画。

li {
    width: 100px;
    height: 100px;
    flex-shrink: 0;
    box-sizing: border-box;
    border: 1px solid green;
    animation: liScroll 1s infinite;
}

@keyframes liScroll {
    0% {
        transform: translate(100px, 0px);
    }

    100% {
        transform: translate(0px, 0px);
    }
}

最终的效果 ⬇️ :

自动轮播跑马灯💡,仅用CSS是否能?

⚠️:lianimation并没有指定animation-timing-function,默认为ease(开始慢,中间快,结束慢)。如果指定为linear(匀速),则会变成「无缝滚动」。

最后

参考文章:

祝大家生活愉快,工作顺利!

「 --- The end --- 」