上设计稿
采用卡片模式,设计师给出的完美设计稿是
显示一行5个卡片,收起左侧菜单与否都展示5个
但是有点经验的前端就知道
这个需求没设计师给的这么简单(虽说后面改的时候也针对于自适应的方案纠结了一天的工期😊)
看到这个需求首先我们第一想到的肯定是自适应的王者:flex
卡片自适应 —— flex
Dom
<div class="card-wrap">
<div class="card-context card-add">+</div>
<!-- vue的遍历,目的是创造data.length个数的card -->
<div class="card-context"
v-for="item in data"
:key="item.id"
>
card
</div>
</div>
CSS
.card-wrap {
display: flex;
flex-wrap: wrap;
justify-content: start;
}
.survey-card-context {
flex: 1;
width: 300px;
min-width: 300px;
height: 210px;
margin: 10px;
}
然后写出了这样的效果
看出问题了吗?
最右侧在card填充不完全的时候,出了一大块空缺,正常审美都忍不了啊!
简单,搞一个justify-content
center/space-around/space-between/space-evenly
这么多属性,总有一个能解决问题
center
.card-wrap {
/*变更*/
justify-content: center;
}
space-around
.card-wrap {
/*变更*/
justify-content: space-around;
}
space-between
.card-wrap {
/*变更*/
justify-content: space-between;
}
这就没有一个长得和设计稿像的啊???
诶?是不是我的max-length有问题?固定宽了,让宽度自适应呢?
去掉max-length的效果
最后一行感觉怎么回事?!
这个完全不大行啊~
心头一紧,赶紧去查了下网上对于card自适应的解决方案。
然后看到了某大佬css计算宽度的复杂方案。加减的多了,我一头雾水。
去了一趟厕所回来的茅塞顿开
最后一行缺几个,那我补几个空div撑开啊。
妙,说干就干
因为我有收起展开,本来就有写resize的方法,直接在resize里写计算就好了。
卡片自适应Max —— flex + 空白card填充
DOM
<div class="card-wrap">
<div class="card-context card-add">+</div>
<!-- vue的遍历,目的是创造data.length个数的card -->
<div class="card-context" v-for="item in data" :key="item.id">
card
</div>
<!-- vue的if语句,目的是添加空card块占位 -->
<div class="card-context no-border" v-if="lastRowBlankColumn >= 1"></div>
<div class="card-context no-border" v-if="lastRowBlankColumn >= 2"></div>
<div class="card-context no-border" v-if="lastRowBlankColumn >= 3"></div>
<div class="card-context no-border" v-if="lastRowBlankColumn >= 4"></div>
</div>
CSS
.card-wrap {
display: flex;
flex-wrap: wrap;
justify-content: start;
}
.card-context {
flex: 1;
width: 300px;
min-width: 300px;
height: 100px;
margin: 10px;
border: solid 3px pink;
display: flex;
justify-content: center;
align-items: center;
font-size: 80px;
}
.card-context.no-border {
border: none;
}
JS
function resize() {
// 以card父元素的宽为参考
const dom = this.$refs.cardListWrap;
let domWidth = dom.offsetWidth;
// 最少2列
let columnNo = 2;
if (domWidth >= 1020 && domWidth < 1340) {
// 3列
columnNo = 3;
} else if (domWidth >= 1340 && domWidth < 1660) {
// 4列
columnNo = 4;
} else if (domWidth >= 1660) {
// 最多5列
columnNo = 5;
}
// 分页器有选择一页多少个的配置
// 新增card的块
// totalBlock是关于这部分的计算,计算当前页总共有几个card
const totalBlock =
this.page.currentPage === 1
? this.data.length + 1
: this.data.length;
// lastRowBlankColumn是计算最后一行需要补几个空白块
this.lastRowBlankColumn =
totalBlock % columnNo > 0 ? columnNo - (totalBlock % columnNo) : 0;
},
效果
card 宽度自适应屏幕,用min-width去约束card,屏幕会尽量排多个。拉伸card的width填充。且最后一行也会正常的card显示。
做的这么完美的适配方案,我去和产品&设计小姐姐们验收,然后她们说:丑???
她们不希望card的宽度变更!!!
我???大费周章???
最后变更
.card-wrap {
/* 变更 */
justify-content: center;
}
.card-context {
/* 新增 */
max-width: 300px;
}
不,我不屈服,我觉得flex不可能容忍我需要加js才能解决这么简单的问题
果真我在知乎看到一篇<a href="https://zhuanlan.zhihu.com/p/51372396" target="_blank">《如何实现同等间隙的卡片布局》</a>的文章中找到了解决方案:flex-grow
卡片自适应Max Pro —— flex-grow
.card-wrap:after {
/* 新增 */
content: "";
display: block;
flex-grow: 99999;
}
删除原有空白div的逻辑和相关在resize的代码,实现的简简单单。
当然这个只限制在固定card宽的模式下
如果不固定card宽度,这个方案不生效。
卡片自适应Pro —— grid
其实中间还去尝试了grid布局,grid布局轻轻松松几行css就能解决最后一行缺失空白的问题,但是因为兼容性的问题没有采用。
具体可以查看阮老师的<a href="http://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html" target="_blank">《CSS Grid 网格布局教程》</a>
这个故事告诉我:有空要好好研究一下flex布局的奇技淫巧
如果大家有更好的方式,一定要在评论里留言赐教呀~