上设计稿

iOS开发 卡片堆叠 UICollectionView ios卡片布局_css

采用卡片模式,设计师给出的完美设计稿是
显示一行5个卡片,收起左侧菜单与否都展示5个
但是有点经验的前端就知道
这个需求没设计师给的这么简单(虽说后面改的时候也针对于自适应的方案纠结了一天的工期😊)

看到这个需求首先我们第一想到的肯定是自适应的王者:flex

1.卡片自适应 —— 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;
}

然后写出了这样的效果

iOS开发 卡片堆叠 UICollectionView ios卡片布局_javascript_02

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

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

center
.card-wrap {
  /*变更*/
  justify-content: center;
}

iOS开发 卡片堆叠 UICollectionView ios卡片布局_css_03

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

iOS开发 卡片堆叠 UICollectionView ios卡片布局_javascript_04

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

iOS开发 卡片堆叠 UICollectionView ios卡片布局_html5_05

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

去掉max-length的效果

iOS开发 卡片堆叠 UICollectionView ios卡片布局_css_06


最后一行感觉怎么回事?!

这个完全不大行啊~

心头一紧,赶紧去查了下网上对于card自适应的解决方案。

然后看到了某大佬css计算宽度的复杂方案。加减的多了,我一头雾水。

去了一趟厕所回来的茅塞顿开

最后一行缺几个,那我补几个空div撑开啊。

妙,说干就干
因为我有收起展开,本来就有写resize的方法,直接在resize里写计算就好了。

2.卡片自适应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;
}
.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显示。

iOS开发 卡片堆叠 UICollectionView ios卡片布局_html5_07

做的这么完美的适配方案,我去和产品&设计小姐姐们验收,然后她们说:丑???
她们不希望card的宽度变更!!!
我???大费周章???

最后变更
.card-wrap {
  /* 变更 */
  justify-content: center;
}
.card-context {
    /* 新增 */
    max-width: 300px;
}

不,我不屈服,我觉得flex不可能容忍我需要加js才能解决这么简单的问题
果真我在知乎看到一篇《如何实现同等间隙的卡片布局》的文章中找到了解决方案:flex-grow

3.卡片自适应Max Pro —— flex-grow
.card-wrap:after {
    /* 新增 */
    content: "";
    display: block;
    flex-grow: 99999;
}

删除原有空白div的逻辑和相关在resize的代码,实现的简简单单。
当然这个只限制在固定card宽的模式下
如果不固定card宽度,这个方案不生效。

4.卡片自适应Pro —— grid

其实中间还去尝试了grid布局,grid布局轻轻松松几行css就能解决最后一行缺失空白的问题,但是因为兼容性的问题没有采用。