最近在项目中碰到这样一个布局,有一个列表,先按照 4 2 的正常顺序排列,当超过 8 个后,会横向重新开始 4 2 的布局,有点像一个个独立的分组,然后水平排列,如下
图中序号是 dom
序列,所以其实这这样的一个顺序
很多同学可能会想到给子元素分组(通过 JS
将原数组拆分组合成一个二维数组),每 8 个套一层容器,然后水平排列就行了
是不是有点麻烦呢?
其实,无需单独嵌套容器也能实现类似分组的效果,这就需要借助本文要介绍的 column
布局了,一起看看吧~
一、简单介绍一下 columns
平时接触较多的都是flex
或者grid
,但还有一个columns
布局往往被忽视了。
https://developer.mozilla.org/zh-CN/docs/Web/CSS/columns
columns
布局,又称“多列”布局(或者“分栏”布局),这是一个使用场景比较有限,但是几乎无法被替代的一种布局。
使用非常简单,直接看一个例子,假设有这样一段文本
p{ width: 500px; }
<p>欢迎关注前端侦探,这里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧,比如这篇文章,如何使用 CSS columns 布局来实现自动分组布局,一起看看吧</p>
默认是这样的
下面我们将段文本分成3列
p{ columns: 3; }
看,自动就分成了3列
并且阅读顺序是从左到右,从上到下,直到整列阅读完成,非常类似以前的报刊读物阅读习惯。
除了指定列数,还可以根据指定宽度自动去计算列数,比如
p{ columns: 100px; }
效果如下
这个表示按照最小100px
去分段,看最多可以分成多少列,并不是说每列就一定是 100
,应该是大于等于 100
,直到剩余空间可以再放下一列。
那为啥设置的是100
,总宽度是500
,却只分成了4
列?原因是有默认列间距,如果去除这个间距
p{ column-gap: 0px; }
这样就刚好被分成了5
列
看不清楚?加个分割线试试
p{ column-rule: 1px solid red; }
是不是刚好分成了 5
列?(注意,这里的分割线是不占空间的)
简单了解columns
多列布局后,下面来看另外的用途
二、columns 实现横向分组布局
可能你已经发现了,上面的文本分列布局和我们文章开头所需要的效果非常类似,都是一列一列的,因此我们可以尝试用columns
布局来实现这样的效果
假设html
是这样的
<div class="wrap"> <div class="list"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div> <div class="item">10</div> <div class="item">11</div> <div class="item">12</div> <div class="item">13</div> <div class="item">14</div> </div> </div>
这里多了一层wrap
是用来做滚动容器的,简单修饰一下
.wrap{ display: flex; width: 400px; overflow: auto; outline: 1px dashed #9747FF; } .item{ display: inline-flex; width: 80px; margin: 10px; aspect-ratio: 1/1; background: #FFE8A3; color: #333; font-size: 30px; border-radius: 10px; align-items: center; justify-content: center; }
效果如下,很正常的一个布局
现在,我们希望纵向高度是固定的,然后横向滚动,先加一个高度试试
.list{ height: 200px; }
这样就变成了纵向滚动的布局了
那么,如何让它横向分栏并且滚动呢?其实非常简单,只需要添加一行
.list{ height: 200px; column-width: 400px; }
设置分栏宽度为滚动容器宽度之后,就自动将整个列表分成多组了,相当于每个滚动屏幕作为一组,从左到右排列,由于空间不足,所以可以横向滚动
是不是非常神奇?仅需一个属性就实现了纵向滚动到横向滚动的切换
三、借助 scroll-snap 实现轮播效果
通常碰到这种横向滚动的效果,你可能会想到一个swiper
组件,也就是那种一屏一屏切换的效果,没错,我们这里也可以借助scroll-snap
轻易实现。
关于
scroll-snap
,网上教程非常多,MDN 官网也有非常清晰的 demo,如果不熟悉的可以先去了解一下:
https://developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-snap-...
这里就不详细介绍了。
回到这里,由于整个列表下面只有一层子元素,好像并没有办法区分每一屏的临界点。其实不然,可以想一下,这里每一屏有 8 个元素,也就是第1
、9
、17
...个分别是每一屏的第一个元素,是不是可以以这些元素为标识(吸附对象)呢?
首先要在滚动容器下定义一下
.wrap{ scroll-snap-type: x mandatory; }
然后给第1
、9
、17
...个元素添加吸附对象,这里可以用nth-child
选择器
.item:nth-child(8n+1){ scroll-snap-align: start; }
效果如下(为了区分,把每一屏的第一个元素背景做了高亮)
还可以多添加点元素,多切几屏看看效果
完整代码可以参考:
- CSS column (codepen.io)')点击预览
四、CSS 实现的优势和总结
相对于传统的 JS
实现来说,有哪些好处呢?
- 少了一层嵌套容器,业务逻辑会更加干净
- 自适应强,可以根据需求选择固定列数或者固定宽度,
JS
往往只能根据数量去分组 - 不会报错,想想看,
JS
中的数组经常会出现xxx.slice is not function
这样的错误,轻则警告,总则整个页面白屏 - 布局足够灵活,想横向滚动就横向滚动,想纵向滚动就纵向滚动,而
JS
方式往往还需要改变数组形态
有这么多好处还不赶紧用起来?下面再来回顾一下columns
布局
columns
布局,又称“多列”布局(或者“分栏”布局),可以将默认的文本流轻易分成多栏,非常类似以前的报刊读物排版column
可以通过宽度(column-width
)去自动分割,或者通过指定数量(column-count
)将布局分成多少栏column-gap
可以设置分栏之间的空隙,默认是有间隔的column-rule
可以设置分隔线,这种分割线是不占据空间的columns
布局使用场景比较有限,但是几乎无法被替代
多想象一下,其实可以有更多的使用场景,虽然本来并不是做这个事情的。
相关内容拓展:(技术前沿)
近 10 年间,甚至连传统企业都开始大面积数字化时,我们发现开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。
针对这类问题,低代码把某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子。极大的提高了程序员的生产效率。
介绍一款程序员都应该知道的软件 JNPF 快速开发平台,基于 Java/.Net 双技术引擎,专注于低代码,采用业内领先的 SpringBoot 微服务架构、支持 SpringCloud 模式,完善了平台的扩增基础,满足了系统快速开发、灵活拓展、无缝集成和高性能应用等综合能力;采用前后端分离模式,前端和后端的开发人员可分工合作负责不同板块,省事又便捷。
免费体验官网:www.jnpfsoft.com/?csdn
最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤