likes
comments
collection
share

纯CSS实现无限循环滚动动画

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

最近接到了一个需求,要求在官网展示一个合作品牌方Logo展示区域,具体需求如下:

  1. 品牌需要分四行展示,每行展示六个品牌logo
  2. 品牌logo宽高为固定大小,且需要隔行错开展示
  3. 品牌logo从右向左线性循环移动展示(跑马灯效果
  4. 双边需要实现模糊的效果

静态效果如下

纯CSS实现无限循环滚动动画

上述这种跑马灯效果其实是有个比较古老的标签<marquee> 可以直接实现的,只不过这个标签现在已经废弃了。那么如何使用CSS来实现上述的需求呢?下面将介绍两种方法来实现。

方法一:通过绝对定位+动画延时

实现思路:

  1. 将logo相对所在行进���绝对定位后,将logo脱离文档流,并定位到所在行的右侧

纯CSS实现无限循环滚动动画

  1. 定义动画,使logo从右往左线性移动,终点的位置也就是相对当前行偏移出一个logo容器的宽度

纯CSS实现无限循环滚动动画

  1. 上述步骤虽然实现了基本的动画,但是所有logo都是堆叠在一起的。所以只能看到一个元素在移动。那么如何将堆叠在一起的动画进行分离呢?这时候动画延时就派上用场了。我们可以根据logo的个数以及动画持续的时间动态计算每个logo动画的延时,从而实现将logo的动画进行分离。

纯CSS实现无限循环滚动动画

  1. 两侧实现模糊遮盖的效果可以通过mask-image + linear-gradient实现。

好了,既然思路已经有了,就可以开始实现了。

步骤

首先,定义HTML的结构如下:

<div class="wrapper">
  <div class="item" style="--count: 1"></div>
  <div class="item" style="--count: 2"></div>
  <div class="item" style="--count: 3"></div>
  <div class="item" style="--count: 4"></div>
  <div class="item" style="--count: 5"></div>
  <div class="item" style="--count: 6"></div>
  <div class="item" style="--count: 7"></div>
  <div class="item" style="--count: 8"></div>
</div>

编写wrapper样式

.wrapper {
	--logo-width: 200px;
	--logo-height: 100px;
	--logo-count: 8;
	--duration: 30s;
  width: 90%;
  max-width: 1200px;
  margin-inline: auto;
  position: relative;
  height: var(--logo-height);
  margin-top: 5rem;
  overflow: hidden;
  /* 模糊遮挡效果 */ 
  mask-image: linear-gradient(
    to right,
    rgba(0, 0, 0, 0),
    rgba(0, 0, 0, 1) 20%,
    rgba(0, 0, 0, 1) 80%,
    rgba(0, 0, 0, 0)
  );
}

定义动画,终点为负的一个logo宽度

@keyframes scrollLeft {
  to {
    left: calc(var(--logo-width) * -1);
  }
}

定义每个item的样式

.item {
  width: var(--logo-width);
  height: var(--logo-height);
  background-color: red;
  border-radius: 6px;
  position: absolute;
  left: calc(var(--logo-width) * var(--logo-count));
  animation-name: scrollLeft;
  animation-duration: var(--duration);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  /* 动态计算出每个logo的动画延时 */
  animation-delay: calc(var(--duration) / var(--logo-count) * (var(--logo-count) - var(--count)) * -1);
}

至于隔行错开的样式,可以添加一个div容器包裹所有的item项目,然后使用CSS伪类选择器,对偶数行应用margin-left来实现。

方案二:通过双份logo进行动画循环

实现思路:

将每行的长度增加一倍,然后通过循环动画来实现无限循环滚动的效果。

纯CSS实现无限循环滚动动画

这种方法的缺点在于会让元素数量增加一倍,有点在于容易理解和实现。

步骤

同样,首先定义HTML结构

<div class="wrapper">
	<div class="marquee">
		<div class="marquee__group">
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
	  </div>
      <div class="marquee__group">
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
	  </div>
  </div>
  <div class="marquee">
		<div class="marquee__group">
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
	  </div>
      <div class="marquee__group" aria-hidden="true">
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
		  <div class="item" ></div>
	  </div>
  </div>
</div>

接着定义CSS样式和动画

.wrapper {
	--logo-width: 200px;
	--logo-height: 100px;
  --gap: calc(var(--logo-width) / 14);
  --duration: 60s;
  --scroll-start: 0;
  --scroll-end: calc(-100% - var(--gap));
  
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  margin: auto;
  max-width: 100vw;
}

.marquee {
  display: flex;
  overflow: hidden;
  user-select: none;
  gap: var(--gap);
  mask-image: linear-gradient(
    to right,
    hsl(0 0% 0% / 0),
    hsl(0 0% 0% / 1) 20%,
    hsl(0 0% 0% / 1) 80%,
    hsl(0 0% 0% / 0)
  );
}

.marquee__group {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-around;
  gap: var(--gap);
  min-width: 100%;
  animation: scrollLeft var(--duration) linear infinite;
}

.wrapper .marquee:nth-child(even) {
  margin-left: calc(var(--logo-width) / -2);
}

.item {
  width: var(--logo-width);
  height: var(--logo-height);
  background-color: red;
  border-radius: 6px;
}

@keyframes scrollLeft {
  from {
    transform: translateX(var(--scroll-start));
  }
  to {
    transform: translateX(var(--scroll-end));
  }
}

最终效果

纯CSS实现无限循环滚动动画

转载自:https://juejin.cn/post/7398376017163337778
评论
请登录