div.carousel
  div.viewport
    // 生成5个轮播卡片
    -for(let i1 = 1; i1 < 6; i1++)
      div.slide(id=`slide-${i1}`)
        // 内容容器
        div.content= i1
        // 前进后退按钮
        a.action-prev(href=`#slide-${i1 == 1 ? 5 : i1 - 1}`)
        a.action-next(href=`#slide-${i1 < 5 ? i1 + 1 : 1}`)
  div.dots 
    // 生成5个控制点
    -for(let i2 = 1; i2 < 6; i2++)
      a(href=`#slide-${i2}`)
View Compiled
@keyframes tonext {
  75% {
    left: 0;
  }
  95% {
    left: 100%;
  }
  98% {
    left: 100%;
  }
  99% {
    left: 0;
  }
}

@keyframes tostart {
  75% {
    left: 0;
  }
  95% {
    left: -400%;
  }
  98% {
    left: -400%;
  }
  99% {
    left: 0;
  }
}

@keyframes snap {
  96% {
    scroll-snap-align: center;
  }
  97% {
    scroll-snap-align: none;
  }
  99% {
    scroll-snap-align: none;
  }
  100% {
    scroll-snap-align: center;
  }
}

.carousel 
  width 560px
  text-align center
  position relative
  box-shadow 0 0 10px rgba(black,.3)
  // 前进后退按钮
  &:before,&:after
    content ''
    width 64px
    height @width
    background #333 url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolygon points='0,50 80,100 80,0' fill='%23fff'/%3E%3C/svg%3E") center/24px no-repeat
    border-radius 50%
    display block
    position absolute
    top 50%
    left -16px
    z-index 10
    pointer-events none
    transform translateY(-50%)
  &:after
    right -16px
    left auto
    background-image url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolygon points='100,50 20,100 20,0' fill='%23fff'/%3E%3C/svg%3E")
  .viewport // 轮播视窗
    display flex
    overflow-x hidden
    scroll-behavior smooth // 实现平滑滚动
    scroll-snap-type x mandatory // 定义容器 x轴滚动 强制处于临时捕捉点
    .slide // 轮播卡片
      width 100%
      height 400px
      font-size 100px
      color white
      background #f99
      flex-shrink 0
      display flex
      justify-content center
      align-items center
      transition transform 0.5s
      position relative
      &:nth-child(even) 
        background-color #99f
      &:last-child
        .content:after
          // 给最后一个轮播卡片设置回到第一张的动画
          animation-name: tostart, snap; 
    .content
      width 100%
      height 100%
      display flex
      justify-content center
      align-items center
      position relative
      &:after // 滚动捕捉点容器
        content ""
        width 100%
        height 100%
        display block
        position absolute
        left 0
        top 0
        pointer-events none
        scroll-snap-align center // 设置临时捕捉点为中心
        // 设置滚动动画
        animation-name tonext, snap 
        animation-timing-function: ease
        animation-duration 4s
        animation-iteration-count infinite
    .action-prev,.action-next // 前进后退按钮
      width 50px
      height @width
      border-radius 50%
      display block
      position absolute
      top 50%
      left 0
      z-index 10
      transform translateY(-50%)
    .action-next
      left auto
      right 0
  .dots // 分页器
    display flex
    justify-content center
    gap 8px
    position absolute
    left 0
    right 0
    bottom 0
    transform translateY(90%)
    a // 控制点
      width 16px
      height @width
      background #333
      border-radius 50%
      display block
      box-sizing border-box

body 
  height 100vh
  font-size 16px
  display flex
  align-items center
  justify-content center
View Compiled
/**
  description: gradually implement <only css carousel>
  source posts link: https://css-tricks.com/css-only-carousel/
  my blog link: https://yogwang.site/2021/CSS-only-carousel/
*/

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.