仅用 HTML 和 CSS 就能做出相当不错的滑块

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

“滑块”,指的是一排盒子,您可以浏览它们。您知道什么是滑块。滑块可能需要很多功能。举个例子,您可能希望滑块能够滑动或滚动。或者,您可能希望这样,而是希望滑块只响应点击或可点击的按钮来导航到幻灯片。或者您可能两者都想要。或者您可能希望将所有这些与自动播放结合起来。

我要说的是,滑块作为一种 UI 组件,其复杂程度足以进入使用 JavaScript 的领域。 Flickity 就是一个很好的例子。我也想说,仅用 HTML 和 CSS 就能做出外观漂亮且功能完善的滑块。从这种方式开始,可以使 JavaScript 更容易,并且,我敢说,这是一个渐进增强的好例子。

首先考虑语义标记。

一堆盒子可能很简单,就像

<div class="slider">
  <div class="slide" id="slide-1"></div>
  <div class="slide" id="slide-2"></div>
  <div class="slide" id="slide-3"></div>
  <div class="slide" id="slide-4"></div>
  <div class="slide" id="slide-5"></div>
</div>

使用少量 CSS 代码,我们可以将它们并排放置并让它们滚动。

.slider {
  width: 300px;
  height: 300px;
  display: flex;
  overflow-x: auto;
}
.slide {
  width: 300px;
  flex-shrink: 0;
  height: 100%;
}

不妨让它在基于 WebKit 的移动浏览器上平滑滑动。

.slider {
  ...

  -webkit-overflow-scrolling: touch;
}

我们可以做得更好!

让我们让每个幻灯片都通过捕捉点捕捉到位。

自从最初发布以来,这方面有一些变化!我正在更新下面的代码块。

.slider {
  ...

  /* CURRENT way. */
  scroll-snap-type: x mandatory;  

  /* OLD WAY. Probably not worth including at all.

  -webkit-scroll-snap-points-x: repeat(300px);
      -ms-scroll-snap-points-x: repeat(300px);
          scroll-snap-points-x: repeat(300px);
  -webkit-scroll-snap-type: mandatory;
      -ms-scroll-snap-type: mandatory;
          scroll-snap-type: mandatory;

   */

}

.slides > div {
  /* CURRENT way. */
  scroll-snap-align: start;
}

看看现在有多漂亮

跳转链接

滑块可能有一个小的 UI 用于跳转到特定的幻灯片,所以让我们也以语义的方式来做,使用锚链接跳转到正确的幻灯片

<div class="slide-wrap">
  
  <a href="#slide-1">1</a>
  <a href="#slide-2">2</a>
  <a href="#slide-3">3</a>
  <a href="#slide-4">4</a>
  <a href="#slide-5">5</a>

  <div class="slider">
    <div class="slide" id="slide-1">1</div>
    <div class="slide" id="slide-2">2</div>
    <div class="slide" id="slide-3">3</div>
    <div class="slide" id="slide-4">4</div>
    <div class="slide" id="slide-5">5</div>
  </div>
  
</div>

锚链接实际上充当指向相关内容的链接,并且具有语义性和可访问性,因此没有问题(如果我错了,请随时纠正我)。

让我们稍微美化一下……我们得到了一些执行其工作的按钮

在桌面和移动设备上,我们仍然可以确保获得流畅的滑动效果!

.slides {
  ...
  
  scroll-behavior: smooth;
}

也许我们只在没有漂亮快速滑动的情况下显示按钮?

如果浏览器支持scroll-snap-type,则它具有漂亮的快速滑动功能。如果我们想隐藏按钮,我们可以这样做

@supports (scroll-snap-type) {
  .slider > a {
    display: none;
  }
}

需要对“活动”幻灯片做一些特殊处理吗?

我们可以为此使用:target。当单击导航幻灯片的按钮之一时,URL 会更改为该 #hash,此时:target 生效。所以

.slides > div:target {
  transform: scale(0.8);
}

有一种方法可以使用 复选框技巧 构建此幻灯片,并仍然使用:checked 对“活动幻灯片”进行操作,但您可能会认为这种方法的语义性和可访问性稍差。

到目前为止,我们已经完成了这些。

查看 Chris Coyier 的 CodePen 上的
简单滑块
(@chriscoyier)
CodePen 上。

事情开始变得有点复杂。

使用:target 是一种巧妙的技巧,但它在以下情况下不起作用:例如,页面加载时没有哈希值。或者如果用户自行滚动或轻扫而不使用按钮。我认为仅用 HTML 和 CSS 无法解决这个问题,也不认为这是 HTML 和 CSS 的完全失败。这只是 JavaScript 的用途之一。

JavaScript 可以确定活动幻灯片是什么。JavaScript 可以设置活动幻灯片。可能值得研究一下 Intersection Observer API

还有哪些限制?

我们已经充分利用了 HTML 和 CSS 在此处的功能。

  • 想要能够用鼠标轻扫?这不是鼠标行为,因此您需要使用 DOM 事件来完成所有操作。任何类型的奇特交互行为(例如物理)都需要 JavaScript。尽管有一个 奇怪的技巧 可以将垂直滚动翻转为水平滚动。
  • 想知道何时更改了幻灯片?就像回调函数?这属于 JavaScript 的领域。
  • 需要自动播放?您可以使用复选框、:checked 和控制@keyframes 动画的animation-play-state 来做一些基本的事情,但效果会有限且不流畅。
  • 想要让它在一个方向上无限滚动,并在需要时重复?这将需要克隆并在 DOM 中移动内容。或者可能滥用<marquee>

我将把这些留给您。我的观点只是,在您需要 JavaScript 之前,您可以做很多事情。从这样一个强大的基础开始可能是最好的方法,无论您在其之上做什么,它都能提供一个良好的回退方案。