无限滚动轮播(仅限 CSS)
Posted
技术标签:
【中文标题】无限滚动轮播(仅限 CSS)【英文标题】:Infinite scrolling carousel (CSS only) 【发布时间】:2022-01-23 07:22:15 【问题描述】:我正在尝试创建一个自动循环播放的轮播。最初我正在实现slick slider
,但后来我遇到了这种仅使用 CSS 的方法:
body
align-items: center;
background: #E3E3E3;
display: flex;
height: 100vh;
justify-content: center;
@keyframes scroll
0%
transform: translateX(0);
100%
transform: translateX(calc(-250px * 7));
.slider
background: white;
box-shadow: 0 10px 20px -5px rgba(0, 0, 0, 0.125);
height: 100px;
margin: auto;
overflow: hidden;
position: relative;
width: 960px;
.slider::before,
.slider::after
background: linear-gradient(to right, white 0%, rgba(255, 255, 255, 0) 100%);
content: "";
height: 100px;
position: absolute;
width: 200px;
z-index: 2;
.slider::after
right: 0;
top: 0;
transform: rotateZ(180deg);
.slider::before
left: 0;
top: 0;
.slider .slide-track
animation: scroll 40s linear infinite;
display: flex;
width: calc(250px * 14);
.slider .slide
height: 100px;
width: 250px;
<div class="slider">
<div class="slide-track">
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/1.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/2.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/3.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/4.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/5.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/6.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/7.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/1.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/2.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/3.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/4.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/5.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/6.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/7.png" />
</div>
</div>
</div>
现在,我正在尝试对我的轮播进行逆向工程并实现类似的功能:
@keyframes scroll
0%
transform: translateX(0);
100%
transform: translateX(calc(-250px * 7));
.carousel
padding: 100px 0;
background: lightblue;
overflow: hidden;
position: relative;
.carousel__wrapper
display: flex;
justify-content: center;
align-items: center;
.carousel__slide
animation: scroll 10s linear infinite;
display: flex;
flex-direction: column;
width: 33%;
.carousel__image
background-size: cover;
background-repeat: no-repeat;
height: 100px;
width: 100px;
margin: 15px 20px;
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<section class="carousel">
<div class="container-fluid px-0">
<div class="row">
<div class="col-12">
<div class="carousel__wrapper">
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/200');"></div>
</div>
</div>
</div>
</div>
</div>
</section>
在我的演示中,carousel
的末尾有空格。而在上面的工作演示中,徽标循环流畅(从头开始,没有空格)。
现在,在上面的工作演示中,我将所有 CSS 剥离为仅此:
@keyframes scroll
0%
transform: translateX(0);
100%
transform: translateX(calc(-250px * 7));
.slide-track
animation: scroll 10s linear infinite;
display: flex;
<div class="slider">
<div class="slide-track">
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/1.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/2.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/3.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/4.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/5.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/6.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/7.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/1.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/2.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/3.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/4.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/5.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/6.png" />
</div>
<div class="slide">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/557257/7.png" />
</div>
</div>
</div>
上面的工作正常,并且上面的 css 存在于我的演示中,但它不能顺利工作?在显示最后一张幻灯片后如何进行过渡(使其从头开始)?
【问题讨论】:
【参考方案1】:轮播基于固定宽度工作。如果有 7 张幻灯片:
-
他们在 html 中复制了一次幻灯片。确保重复幻灯片。
carousel__wrapper
已提供width: calc(250px * 14);
。要显示的幻灯片数量的两倍。请注意,包装器取决于幻灯片宽度,而幻灯片不依赖于包装器。
carousel
的宽度小于包装器 250px * 4
的宽度,溢出被隐藏,因此我们只能看到窗口而不是整个 carousel__wrapper。
动画将幻灯片向左移动calc(-250px * 7)
。这里,250px 是幻灯片宽度。请注意,它们仅移动了 7 张幻灯片,而不是全部 14 张。
如果不使用 javascript,您将无法使用相对尺寸。为了只保留 CSS,您需要绝对宽度。 如果你使用变量,那么事情将很容易维护和理解:
:root
--no-of-slides: 6;
--slides-in-view: 4;
--slide-width: 200px;
--slide-height: 300px;
--iteration-time: 10s;
@keyframes scroll
0%
transform: translateX(0);
100%
transform: translateX(calc(var(--slide-width) * var(--no-of-slides)* -1));
.carousel__wrapper
display: flex;
/*justify-content: center;*/
align-items: center;
width: calc(var(--slides-in-view) * var(--slide-width));
overflow: hidden;
border: 1px dashed gray;
margin: 0 auto;
.carousel
padding: 100px 0;
background: lightblue;
overflow: hidden;
width: calc(2 * var(--no-of-slides));
.carousel__slide
animation: scroll var(--iteration-time) linear infinite;
display: flex;
flex-direction: column;
flex: 0 0 auto;
width: var(--slide-width);
height: var(--slide-height);
box-sizing: border-box;
/*border: 1px dotted darkblue;*/
.carousel__image
background-size: cover;
background-repeat: no-repeat;
height: 50%;
/*width: 100px;*/
margin: 15px 20px;
/* just for analysis remove this 3 rules later*/
.carousel__slide
position: relative;
.carousel
counter-reset: slideNo;
.carousel__slide::before
counter-increment: slideNo;
content: counter(slideNo);
position: absolute;
top: 0%;
left: 50%;
font-size: 2rem;
color: lime;
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<section class="carousel">
<div class="container-fluid px-0">
<div class="row">
<div class="col-12">
<div class="carousel__wrapper">
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
</div>
<!--#### repeat ####-->
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
</div>
</div>
</div>
</div>
</div>
</section>
在上述 CSS 规则中,我的更改位于空行之后。请参阅代码中的 cmets。
如果您想要基于视口的尺寸,那么您可以使用vw
和vh
单位:
:root
--no-of-slides: 6;
--slides-in-view: 4;
--slide-width: 33vw;
--slide-height: 50vh;
--iteration-time: 10s;
@keyframes scroll
0%
transform: translateX(0);
100%
transform: translateX(calc(var(--slide-width) * var(--no-of-slides)* -1));
.carousel__wrapper
display: flex;
/*justify-content: center;*/
align-items: center;
width: calc(var(--slides-in-view) * var(--slide-width));
overflow: hidden;
border: 1px dashed gray;
margin: 0 auto;
.carousel
padding: 10px 0;
background: lightblue;
overflow: hidden;
width: calc(2 * var(--no-of-slides));
.carousel__slide
animation: scroll var(--iteration-time) linear infinite;
display: flex;
flex-direction: column;
flex: 0 0 auto;
width: var(--slide-width);
height: var(--slide-height);
box-sizing: border-box;
/*border: 1px dotted darkblue;*/
.carousel__image
background-size: cover;
background-repeat: no-repeat;
height: 50%;
/*width: 100px;*/
margin: 15px 20px;
/* just for analysis remove this 3 rules later*/
.carousel__slide
position: relative;
.carousel
counter-reset: slideNo;
.carousel__slide::before
counter-increment: slideNo;
content: counter(slideNo);
position: absolute;
top: 0%;
left: 50%;
font-size: 2rem;
color: lime;
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
<section class="carousel">
<div class="container-fluid px-0">
<div class="row">
<div class="col-12">
<div class="carousel__wrapper">
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
</div>
<!--#### repeat ####-->
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/1/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/2/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/3/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/4/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/5/200/300');"></div>
</div>
<div class="carousel__slide">
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
<div class="carousel__image" style="background-image: url('https://picsum.photos/seed/picsum/200/300');">
</div>
</div>
</div>
</div>
</div>
</div>
</section>
【讨论】:
特别感谢使用vars
的可重用性:) 非常感谢!以上是关于无限滚动轮播(仅限 CSS)的主要内容,如果未能解决你的问题,请参考以下文章