纯 CSS 水平滚动

Avatar of Pieter Biesemans
Pieter Biesemans 发布

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

网络是一个相当垂直的地方。您阅读网站就像阅读纸质页面一样:从左到右,从上到下。但有时,您可能希望摆脱这种垂直性,尝试一些疯狂的事情:创建一个水平列表。或者更疯狂一点,创建一个水平网站!

如果我们可以做这样的事情就好了

/* This isn't real */
div {
  scroll-direction: horizontal;
}

不幸的是,这不可能实现。甚至不在 CSS 的路线图上。

这太可惜了,因为在我工作的公司,这将非常有用。我们做了很多网络演示。演示是一种非常水平的事情——通常幻灯片具有 4:3 或 16:9 的纵横比。这意味着我们总是在演示的水平性和网络技术的垂直性之间苦苦挣扎。而我所说的“我们”,指的是我本人。但如果说我喜欢什么,那就是挑战。

另一个用例

导致我深入研究这个想法的具体用例是,一个客户希望在一张幻灯片上展示他们所有的产品。当然,他们的产品目录太大,无法放入单个视图中。因此,我们决定将它们分成三个类别,每个类别都可水平滚动。这样,每个类别中最重要的三个产品都可见,不太重要的产品仍然易于访问。

非 JavaScript 方法

毫不奇怪,有很多方法可以在 JavaScript 中做到这一点。其中一些 就在这个网站上

我很好奇是否可以用纯 CSS 来实现。解决方案最终相当简单

  • 创建一个包含项目的容器
  • 将容器逆时针旋转 90 度,使 底部 位于 右侧
  • 将项目旋转回正确的方向

步骤 1) 设置容器

创建一个 <div>,并创建一些子元素。

在本例中,我们的侧向滚动容器将宽 300px,包含 8 个 100×100px 的项目。这些是任意大小;它们可以是任何尺寸。

<div class="horizontal-scroll-wrapper squares">
  <div>item 1</div>
  <div>item 2</div>
  <div>item 3</div>
  <div>item 4</div>
  <div>item 5</div>
  <div>item 6</div>
  <div>item 7</div>
  <div>item 8</div>
</div>

容器的高度将变成“宽度”,反之亦然。因此,在下面,“宽度”我们的容器将是 300px

.horizontal-scroll-wrapper {
  width: 100px;
  height: 300px;
  overflow-y: auto;
  overflow-x: hidden;
}

现在是子元素

.horizontal-scroll-wrapper > div {
  width: 100px;
  height: 100px;
}

步骤 2) 旋转容器

现在我们使用 CSS transform 将容器旋转 -90 度。就是这样:一个水平滚动条。

.horizontal-scroll-wrapper {
  ...
  transform: rotate(-90deg);
  transform-origin: right top;
}

只有一个微小的问题:我们的子元素也旋转了,现在其中的任何内容都处于倾斜状态。

步骤 3) 将子元素旋转回垂直方向

我们如何将子元素恢复到垂直方向?使用另一个相反的 CSS transform 将它们旋转回来。

.horizontal-scroll-wrapper > div {
  ...
  transform: rotate(90deg);
  transform-origin: right top;
}

步骤 4) 修复定位

它开始看起来不错了,但仍然存在一些问题。

通过使用右上角作为锚点旋转包装器,我们的左侧已根据容器的宽度进行了偏移。如果您发现难以理解这一点,只需将手指放在页面右上角并旋转它即可。解决方案:使用 translateY 将其移回。

更好一些。但是,第一个项目仍然丢失,这是由于项目发生了相同的现象。我们可以通过为第一个子元素提供其宽度的顶部边距或通过像包装器一样转换所有项目来解决此问题。不过,我发现最简单的方法是在包装器中添加一个等于项目宽度的顶部填充,为项目创建一种缓冲区。

.horizontal-scroll-wrapper {
  ...
  transform:rotate(-90deg) translateY(-100px);
  ...
}

演示

查看 CodePen 上 Pieter Biesemans 的笔 水平滚动(简单示例)@pieter-biesemans)。

这里还有另一个,您可以看到非正方形的子元素

查看 CodePen 上 Pieter Biesemans 的笔 水平滚动(扩展示例)@pieter-biesemans)。

兼容性

我在我身边可用的设备上进行了测试。

设备 操作系统 浏览器 正常工作?
台式机 Win10 Chrome 54
台式机 Win10 Firefox 47 是(带滚动条)
台式机 Win10 IE11 是(带滚动条)
台式机 Win10 Opera 41
台式机 Win10 Vivaldi 1.4
笔记本电脑(触摸屏) Win10 Chrome 54
三星 Galaxy S3 Android 4.3 Chrome 移动版 52
三星 Galaxy S6 Android 5.0 Chrome 移动版 52
Nexus 6P Android 6 Chrome 移动版 52
iPad2 iOS Chrome 移动版 52
iPad2 iOS Safari 移动版 9.0
iPad Air 2 iOS Safari 移动版 9.0

台式机

由于滚动条的样式目前仅受 WebKit/Blink 支持,因此 Firefox 和 IE 仍然显示难看的灰色滚动条。您可以使用 JavaScript 嗅探出这一点并完全隐藏它们,但这属于另一个教程的内容。

使用鼠标滚轮在台式机上效果很好。不过,我的笔记本电脑情况有所不同。触摸屏和触控板都表现得好像 div 没有旋转。

移动设备

我有点惊讶地发现 Android 实际上理解了容器已旋转,并允许您通过左右滑动进行横向滚动。

另一方面,iOS 却无法正常工作。它表现得好像容器没有旋转,因此您必须上下滑动才能横向滚动,这当然不直观。此外,左右滑动会使项目在其包装器中上下移动,这既出乎意料又奇怪。将溢出设置为隐藏并不能缓解此问题。

结论

根据Can I Use网站的数据,CSS 变换目前已被超过93%的用户支持(截至本文撰写之时,2016年11月),所以这方面没有问题。

但是,请注意在生产环境中使用它。我已在一些设备上测试过此方法,但测试范围并不广泛或深入。

最大的问题在于触控输入,它需要你上下滑动来左右移动。一个可能的解决方案是在你的网站上添加一条消息来解释这一点,但这需要依赖于用户实际阅读你的消息。即使这样,它仍然会违反直觉。另一个可能的解决方案是在这些设备上使用 JavaScript 捕获触控输入,但那样的话,你最好直接用 JavaScript 实现整个功能,并完全放弃这个 CSS 技巧。