网络是一个相当垂直的地方。您阅读网站就像阅读纸质页面一样:从左到右,从上到下。但有时,您可能希望摆脱这种垂直性,尝试一些疯狂的事情:创建一个水平列表。或者更疯狂一点,创建一个水平网站!
如果我们可以做这样的事情就好了
/* 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 技巧。
我以前从未听说过这种技巧。但即使读了两遍文章,我仍然不太确定你想用它来解决什么具体问题。例如,为什么不使用真正的原生水平滚动,比如通过使用
white-space: nowrap
阻止换行并使用inline-block
元素?就必要的布局技巧而言,这要简单得多,并且可以在任何设备上工作,而不管输入类型如何。你费这么大劲,只是为了让滚轮水平滚动吗?
我正准备写一个类似的回复。我会坚持使用
overflow-x: scroll
,因为演示看起来有点奇怪,需要向下滚动才能向右移动。不过,看到另一种解决问题的方法很有意思 :)
整个要点是让原生滚动横向移动而不是纵向移动。这很奇怪。这是一个技巧。
是的,正是如此。而且因为我可以。
因此,它在 iOS 上不起作用,在 Android 上的行为类似于
overflow-x: scroll
,并在(某些)桌面设备上使垂直滚动水平滚动,因为,好吧,为什么不呢,这是一个技巧!说得对。我倾向于认为让垂直滚轮水平滚动与你在文章中指出的触控设备问题(使垂直滑动左右滚动)一样糟糕,因为实际上,两者都存在违反用户预期的相同问题。
作为用户,如果你想在非触控设备上原生地水平滚动,你可以按住 Shift 键并滚动滚轮。当然,几乎没有用户知道这一点,因此作为开发人员,我应该通过提供导航按钮和滚动条来帮助他们,而不是以糟糕的方式修改 CSS 布局,并搞乱触控设备用户的原生滚动。;)
无论如何,我明白了——这是一个技巧。
或者我们可以只使用 flexbox 而不进行换行。我最近在主横幅的http://xoroshe.pl 上做了这个。
哦,我没有理解这一点,抱歉。
你也可以使用 css multicol(因此,我们不需要计算或知道宽度)
https://escss.blogspot.com/2015/03/mouse-wheel-down-scroll-right.html
我不能建议使用这个 CSS 技巧。缺点太大了。不过,想法很巧妙。谢谢,Pieter。
嗨,没问题。我从未说过你必须使用它。我也不会在生产环境中使用它。
在 Chrome 桌面版上,它似乎与笔/平板电脑输入不兼容(这是我的主要指向设备)。它强制滚动运动为垂直方向,而使用默认浏览器滚动时,水平滚动可以完美工作。
确实如此。在我的触摸屏笔记本电脑上,它的行为也大致相同。这就是为什么我不会在生产环境中使用它。但嘿,练习的目的是看看我是否可以破解它 :)
可访问性也是一个问题。对于无法使用鼠标(甚至滚轮)的人来说,你可能需要另一种左右滚动的机制。
但这是一个跳出框框思考的绝佳例子。我自己也创建了一个使用水平滚动区域的网站;我使用 css 列来实现它。这可能更直接。
可访问性绝对是一个问题,大多数输入设备都会在这个方面出问题。我相当惊讶 Android 没有出现问题。
我不会说这比使用列更直接,相反。这更像是一个练习,看看我是否可以而不是我是否应该。
我不知道你们是怎么想的,但我阅读的每一篇文章,我都会阅读引言段落以了解文章的要点,而这篇的引言段落非常清楚地说明了文章的目的。目的是将此用作演示工具入门套件,用于展示幻灯片。
我认为 Pieter 只使用 CSS 开发解决方案的方式很酷,因为有些环境甚至不允许使用 JavaScript。
伟大的 Pieter,感谢分享。
欢迎你,lcr。我希望你喜欢它,并激励你敢于尝试和破解事物。
为什么不直接使用
overflow-x: auto
呢?不支持鼠标滚轮。
嗨,Jens,整个要点是让滚轮做一些它通常不做的事情:向右滚动。如果你愿意,这是一种 CSS 技巧或黑客手段,你通常只能用 JavaScript 实现。
是的,
大约 6 个月前,我在 Codepen 上做了相同的练习,测试的几个浏览器让我得出相同的结论:对于这种情况,浏览器行为差异太大,无法信任。
嗨,Mehdi,我知道我不可能是第一个想到如此简单的事情的人。感谢分享。
嗨
几天前我遇到了同样的问题,并设法通过稍微有点 hacky 的方式使用 white-space:nowrap; 来解决它。
我得到的结果:https://jsfiddle.net/mzvaan/590grzuy/
嗨,Matej,这通常是我会做的事情。不过,这个练习的重点是制作一个可以使用鼠标滚轮滚动的横向滚动器。但它很 hacky,并且在触控设备等设备上的表现不太好,所以目前我们只能使用
white-space: nowrap
。嗯,他们在 medium.com 的顶部菜单中做得简单得多。他们在父元素上使用 white-space: nowrap、overflow-x: auto;,在子元素上使用 letter-spacing:0;,然后在子元素内部应用正确的字母间距。
嗨,Chris,这通常是我在生产环境中会做的事情。不过,这个练习的重点是制作一个可以使用鼠标滚轮滚动的横向滚动器。但它很 hacky,并且在触控设备等设备上的表现不太好,所以目前我们只能使用 white-space: nowrap。
在这里,我放了一个在桌面和移动设备上都能正常工作的简单演示
http://codepen.io/bassta/pen/gLXWKm
可能需要一些指示器来表明可以滚动
标记
样式
@Chris Panayotov 这个想法是通过鼠标滚轮向右滚动
啊,但这需要以适合平台的方式滚动,例如使用 shift + 滚轮,或用手指按与滚动匹配的方向拖动。谁想那样做呢?
这篇文章通过允许你在某些平台上无需 shift 键即可使用垂直滚轮水平滚动来解决这个显而易见的问题,但在 Android、iOS 或带触摸屏的笔记本电脑上却无法实现。但你肯定可以在可以使用 shift + 滚轮的平台上做到这一点,这样可以节省一次按键。
我很好奇,这个网站是怎么做到的?
它表现得好像容器没有旋转,所以你必须上下滑动才能横向滚动,这当然是不符合直觉的。
上下滚动来横向滚动直观吗?
这个练习的重点是仅使用 CSS 重新创建此演示:https://css-tricks.cn/examples/HorzScrolling/
但不可否认,使用鼠标滚轮向下滚动以横向移动也不是很直观。
纵横比*
正确。观察得很仔细。
我刚刚关闭了一个使用横向滚动的网站(来自 css-tricks 的链接)。
因为它使用了横向滚动。
如果您试图将这个离线的、纸质的概念转移到在线世界,您可能在某个地方走错了路。您在这里描述的任何用例都不会从横向滚动中获得更好的结果。
互联网不是书,您的浏览器也不是杂志。与媒介一起工作并为媒介服务,而不是违背它。
退一步,阅读https://en.wikipedia.org/wiki/Form_follows_function。
我理解并听到了你说的话。
但要小心不要过于教条主义:https://css-tricks.cn/increasing-wariness-dogmatism/
嗨,Chris,
我在 iOS 上旋转时遇到了问题,看起来 iOS 会忽略旋转是否是 90 的倍数,如果将其更改为 89.9,它应该可以工作。
希望这有帮助
Cleber Santana 的评论,比赛结束后的评论
Jari Thorup Palo 对此概念的看法