卡片布局自适应方案全解析

上设计稿

设计稿大概.gif

采用卡片模式,设计师给出的完美设计稿是
显示一行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;
}

然后写出了这样的效果

demo1.gif

看出问题了吗?
最右侧在card填充不完全的时候,出了一大块空缺,正常审美都忍不了啊!

简单,搞一个justify-content
center/space-around/space-between/space-evenly
这么多属性,总有一个能解决问题

center
.card-wrap {
  /*变更*/
  justify-content: center;
}
center.png
space-around
.card-wrap {
  /*变更*/
  justify-content: space-around;
}
space-around.png
space-between
.card-wrap {
  /*变更*/
  justify-content: space-between;
}
space-between.png

这就没有一个长得和设计稿像的啊???
诶?是不是我的max-length有问题?固定宽了,让宽度自适应呢?

去掉max-length的效果

宽度自适应.png

最后一行感觉怎么回事?!
这个完全不大行啊~
心头一紧,赶紧去查了下网上对于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.gif

做的这么完美的适配方案,我去和产品&设计小姐姐们验收,然后她们说:丑???
她们不希望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布局的奇技淫巧
如果大家有更好的方式,一定要在评论里留言赐教呀~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容