《uni-app》移动端纯CSS实现不等高的瀑布流效果
前言
前两天无意中看到朋友在玩小红书,第一眼就被其瀑布流的布局给吸引住了,感觉非常有意思,之前知道有这种布局,但大多数都是在web端,移动端上还是首次见到,因此特别想试试~
这一章节,玩一点好玩的,移动端或者直接说uni-app能否使用 纯CSS 实现瀑布流的布局效果~ 我们知道,不等高的瀑布流布局可以给用户造成视觉上的错位,非常具有美感,实际上绝大多数项目中的的瀑布流都是借助于JavaScript实现的,通过JavaScript动态计算每一个DOM的尺寸与坐标,最终实现布局,毫无疑问,这种就是目前的最优解;
但是,布局这东西不应该是CSS的领域么,那么 纯CSS 能不能实现呢,我觉得是可以的,虽然有不少问题无法解决…
示例
可能会有小伙伴问,什么是瀑布流布局,简单看两种示例吧,一看就明白了的
WEB端示例
移动端示例
这种就是不等高的瀑布流布局,还是比较一目了然的;
瀑布流实现
先看一下原始状态吧,原始状态的图片效果如下
第一种: flex
flex布局作为现代前端开发最常用的布局方式,那么flex能不能实现瀑布流呢,答案是可以的,虽然不完美,但确实是实现了
核心代码
核心利用的就是 flex的纵向布局,以及当超出高度时自动换行,也就是这两行代码
flex-direction: column;
flex-wrap: wrap;
以及当纵向排序而非横向排序时必须借助 order属性进行重新排序;
order:1
实现
我们知道,flex 默认时沿着X轴进行排布的,并且超出后也不会换行,即是设置了flex-wrap: wrap;
也是这种,如下图展示
并且,还会有一个致命的问题,即同一行的高度是保持一致的,它并 不会因为其中一张高度低下方的图片就自动补上空缺的位置,具体细节可以参考下图
既然不会自动补上空缺,那是不是就没办法了,那肯定不是,我们不妨换个思路,flex在同一行内会不断的往前顶补空位,那是不是代表如果纵向排列,一列之间会不断的往上补位,因为一列等同于横着时候的一行,那么结果就会变成 不同列之间的起始的位置是同一个水平的,但同一列之内它不会有空隙,对代码尝试了修改,加添方向后的代码如下:
<template>
<view class="content">
<view class="img-container" v-for="(item,index) in list" :key="index">
<img class="img-style" :src="item.src" :style="{height:item.height}" />
<div>
标题{{index}}
</div>
</view>
</view>
</template>
<style>
.content {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.img-container{
position: relative;
width: 375rpx;
padding-bottom: 0;
box-sizing: border-box;
}
</style>
编写代码后发现,这么写的 图片超出屏幕后并没有自动新开启一列,而是有多少张图片,这一列就有多高
我们不能让他无限变高,必须限定一个高度,只有限定了高度,超出时才会自动新起一列,我们给父级容器加上个高度
height
<style>
.content {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 1100px;
}
.img-container{
position: relative;
width: 375rpx;
padding-bottom: 0;
box-sizing: border-box;
}
</style>
得到结果如下:
看起来有点相像了,但是我们知道,这个图片它是纵向排列的,就如上图中的线条图那种,不信我们可以标签看一下,加上如下CSS代码
.img-container{
position: relative;
width: 375rpx;
padding-bottom: 0;
box-sizing: border-box;
counter-increment: item-counter;
}
.img-container::after{
position: absolute;
top: 10rpx;
right: 10rpx;
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
background-color: #000;
color: #fff;
content:counter(item-counter);
}
加上后,我们可以得到一个标签,如下图所示(因为标题的文字还需要排版,所以先去掉了)
确实是纵向排列的,但 理论上我们需要的是横向排列,我们得找一个办法将这个 布局方式改为横向排列,那必须要借助一个叫
order
的值了
order 属性 设置或检索弹性盒模型对象的子元素出现的順序。
因此,借助 order属性
我们可以给所有的 img-container
按照比例进行排序(注意,这个属性只对flex布局生效),也就是如下
.img-container:nth-child(2n+1){
order: 1;
}
.img-container:nth-child(2n){
order: 2;
}
得到效果图如下:
缺点
至于缺陷,自然是有的,其实我们一开始就说了,一切的一切都 必须借助于flex容器高度固定这个基础上,如果这个值没有,下面这些实现都是不可能的,如果实际项目中想要用flex实现瀑布流布局,那么 一定要对高度进行精确的计算,否则很容易出现图片叉了的情况,比如出现了第三列这种,完全超出了预期…
完整代码
<template>
<view class="content">
<view class="img-container" v-for="(item,index) in list" :key="index" >
<img class="img-style" :src="item.src" :style="{height:item.height}" />
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello',
list:[
{
src:"https://picsum.photos/300/400?random=1",
height:"180px"
},{
src:"https://picsum.photos/300/420?random=2",
height:"220px"
},{
src:"https://picsum.photos/300/460?random=3",
height:"240px"
},{
src:"https://picsum.photos/300/380?random=4",
height:"160px"
},{
src:"https://picsum.photos/300/420?random=5",
height:"220px"
},{
src:"https://picsum.photos/300/440?random=6",
height:"260px"
},{
src:"https://picsum.photos/300/500?random=7",
height:"220px"
},{
src:"https://picsum.photos/300/490?random=8",
height:"200px"
}
]
}
},
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 1100px;
}
.img-container{
position: relative;
width: 375rpx;
padding-bottom: 0;
box-sizing: border-box;
counter-increment: item-counter;
}
.img-container:nth-child(2n+1){
padding-left: 10rpx;
padding-right: 5rpx;
}
.img-container:nth-child(2n){
padding-left: 5rpx;
padding-right: 10rpx;
}
.img-container .img-style{
width: 100%;
}
.img-container::after{
position: absolute;
top: 10rpx;
right: 10rpx;
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
background-color: #000000;
color: #ffffff;
content:counter(item-counter);
}
.img-container:nth-child(2n+1){
order: 1;
}
.img-container:nth-child(2n){
order: 2;
}
</style>
第二种:column-count及column-gap
这两个属性…我相信可能好多人都没有见过…简单的介绍一下吧,column-count
,这是一个CSS3的属性,官方说明如下:
column-count CSS 属性,描述元素的列数。
简单的说,它的作用只有一个,指定某个元素内部应当分为几列,就这么简单粗暴,而 column-gap
的官方说明如下:
CSS column-gap 属性用来设置元素列之间的间隔(gutter)大小。
这个属性得和 column-count
配合使用,作用就是 指定列于列之间的间隔宽度,这两个属性对兼容性还是由一些要求的,但好在移动端的容器版本都不会老,因此 如果仅在移动端使用,还是有些可行性的~
核心代码
column-count: 2;
column-gap: 0;
核心代码就这两行,一行申明几列,一行声明间隔;
实现
依旧是上一节中的原始代码,我们只需要在父容器加上这两行代码
.content {
column-count: 2;
column-gap: 0;
}
就会得到如下结果
是不是已经非常像了,而且比 flex布局还要简单,毕竟只有2行代码,那么排列方向呢?很遗憾,还是纵向排列的,我们加上上一节中的伪类,对每张图片进行一个标记,得到如下结果
有没有办法改为横向排列呢,好像是没有,至少博主没有找到,
order
这个属性是针对 flex
的,普通的盒模型并不会生效~
缺点
缺点很明显了,就是排列顺序 仅仅支持纵向排列,它不支持横向,和 flex布局
相对,优点就是实现简单,也不需要计算高度
完整代码
<template>
<view class="content">
<view class="img-container" v-for="(item,index) in list" :key="index" >
<img class="img-style" :src="item.src" :style="{height:item.height}" />
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello',
list:[
{
src:"https://picsum.photos/300/400?random=1",
height:"180px"
},{
src:"https://picsum.photos/300/420?random=2",
height:"220px"
},{
src:"https://picsum.photos/300/460?random=3",
height:"240px"
},{
src:"https://picsum.photos/300/380?random=4",
height:"160px"
},{
src:"https://picsum.photos/300/420?random=5",
height:"220px"
},{
src:"https://picsum.photos/300/440?random=6",
height:"260px"
},{
src:"https://picsum.photos/300/500?random=7",
height:"220px"
},{
src:"https://picsum.photos/300/490?random=8",
height:"200px"
}
]
}
},
}
</script>
<style>
.content {
column-count: 2;
column-gap: 0;
}
.img-container{
position: relative;
width: 375rpx;
padding: 4px;
padding-bottom: 0;
box-sizing: border-box;
counter-increment: item-counter;
}
.img-container .img-style{
width: 100%;
}
.img-container::after{
position: absolute;
top: 10rpx;
right: 10rpx;
display: block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
background-color: #000000;
color: #ffffff;
content:counter(item-counter);
}
</style>
小结
本文分享了 两种实现瀑布流布局的纯CSS办法,他们各有优缺点,大致如下:
- flex:支持横向排序,但父容器必须计算高度,而且是精准的高度,没有高度,那么布局将实现不了;
- column:不支持横向排序,实现有效并且非常简单;
(PS:都已经看到这里了,点个赞,求个关注吧,万分感谢~)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。