本文首发于 vivo 互联网技术 微信公众号
链接:https://mp.weixin.qq.com/s/6O0CH0U_WE1YkPK75m-jDQ
作者:悟地面台研发团队
一、背景
明天来给大家分享一下栅格布局计划。在后盾展现页面中,常见卡片列表的展现需要。然而这类展现型需要其实不容易满足,有以下两个问题。
1、优化前的问题
(1)PC 分辨率不对立
用户在应用治理后盾时,关上浏览器页面宽度不一。支流的显示宽度 1920 像素,但也存在 1366,1600 等其余宽度的场景。而且用户在桌面端搭建页面时,同时在操作的内容不仅仅是治理后盾,可能会适当放大页面宽度来做其余的事件。这样咱们在页面布局时须要思考到兼容宽泛的屏幕宽度。
(2)一份设计稿
无论是前端开发还是设计师,在页面布局时,都心愿能兼顾到不同终端场景下的展现差别,然而设计师不可能去针对性做出多套设计稿,来针对内容进行自适应设计。尚待有一种更加通用,且又轻量的计划供参考应用。
2、优化前的计划
在卡片列表展现的页面,往往会实现一种对立尺寸的卡片顺次排列,或者一行展现固定数量的卡片,宽度动静调整。这两种布局形式是咱们实现展现类需要的常备计划。
然而这两种常备计划,只是简略的解决了设计稿所出现的分辨率展现诉求,在页面宽度有调整时,展现成果就不尽如人意了。
(图 1 – 优化前的计划)
(1)固定卡片宽度
在页面宽度进行调整时,页面左右侧会有较大幅度的空白,没有展现具体的内容。
(2)固定卡片个数
在页面宽度过大或者宽度过小时,卡片容易放大放大至十分夸大的比例,展现的成果欠佳。
二、布局计划剖析
鉴于目前简略的计划无奈满足宽泛页面宽度的诉求,咱们能够对行业内多种自适应布局计划进行调研,来对咱们最终的布局计划做出肯定水平的参考。为了兼容页面不同宽度的状况,咱们先将页面上布局元素进行一个简略的分类,布局的组成部分为 卡片宽度,卡片外边距,容器内边距。自适应栅格布局,就是动静的调整这三个影响因子,来实现页面更现实的展现。
- 卡片宽度:卡片的宽度随着页面宽度自适应调整
- 卡片外边距:卡片相互之间的边距随着页面宽度自适应调整
- 容器内边距:容器的内边距随着页面宽度自适应调整
(图 2 – 影响因子)
1、行业内的计划
咱们这里收集了三种常见的行业内解决方案,来进行一一列举。
(1)谷歌 Material Design
谷歌的 Material Design,是一套大一统的自适应布局解决方案,将页面宽度划分为 13 种场景,在达到这 13 种场景的临界点时,调整自适应布局的三个影响因子,来实现对立的自适应成果。该计划的长处是以谷歌的设计规范为底本,可能在一类产品中实现对立的布局格调。如果你的产品心愿以谷歌的设计规范为依靠,并且前期不会做个性化调整,谷歌的 Material Design 是很好的抉择。
(图 3 – 谷歌 Material Design)
(2)定制栅格的计划
定制栅格计划罕用于企业官网或者视频网站。国内常见的视频网站,在首页展现视频内容时,就用到了这种定制栅格的计划,实质上就是在不同的分辨率区间,应用不同的设计稿。这种计划适宜于设计资源比拟丰盛的团队,可能基于自适应的要求,给出多套实现的设计稿,并给出一套外部的定制化栅格计划。
(图 4 – 定制栅格的计划)
(3)自适应栅格计划
自适应栅格计划,就是有一套计算公式,能够套用给页面宽度和页面布局三个影响因子,通过固定其中两项因子的值,计算出第三项因子的值,来实现页面布局的成果。这个计划适宜于团队对设计资源要求不高,并且对展现成果有较高的要求的场景。
2、自适应计划剖析
上面简要论述三种自适应栅格计划各自的应用场景,和优缺点剖析:
(表 1 – 自适应栅格计划比照)
(1)自适应卡片计划
通过固定页面边距和卡片边距的尺寸来计算出卡片宽度,该计划的长处是整体框架稳固,卡片自适应伸缩。毛病是调整浏览器宽度时,卡片尺寸不可避免时大时小,卡片外部的元素要依照百分比布局,肯定要做好自适应。
(图 5 – 自适应卡片计划)
(2)自适应内边距计划
通过固定卡片边距和卡片宽度的尺寸来计算出页面边距,该计划的长处是,卡片展现内容整体居中,卡片宽度也不会有变动,卡片外部能够严格还原设计稿;但毛病是,卡片内容在大屏内会显得太小,然而在小屏上会显得很大。
(图 6 – 自适应内边距计划)
(3)自适应边距计划
通过固定页面边距和卡片宽度的尺寸来计算出卡片边距,该计划的长处是,页面左右两侧不会有太大的空白区域,卡片宽度也不会有变动,卡片外部能够严格还原设计稿;但毛病是卡片边距会动静调整,这种场景中卡片间接的间隔往往比拟大,这样视觉效果更好。
(图 7 – 自适应边距计划)
3、计划总结
行业内这三个计划各有不同的实用场景。
- Material Design 计划适宜于团队设计资源投入少,设计格调以谷歌 Material Design UI 为准,且前期不会做个性化调整的团队。
- 定制化栅格计划适宜于团队设计资源丰盛且定制化强的团队。
- 自适应栅格计划适宜于团队设计资源投入少且栅格格调更加个性化的团队。
悟空团队基于团队业务需要和设计成果,决定应用自适应栅格计划,上面是咱们的栅格计划实现。
(图 8 – 悟空栅格实现)
三、自适应栅格计划 – 栅格组件实现
咱们依据自适应栅格计划实现了自适应栅格组件,三种自适应栅格计划能够应用同一个组件来实现,咱们首先看看栅格组件如何进行应用。
1、组件应用形式
自适应栅格组件蕴含外层的容器组件 Grid 和内置的卡片组件 GridItem,容器组件有四个根底配置项和三个定制化配置项。
以下是容器组件 Grid 的根底配置项,Grid 依据根底配置项粗算出一行展现的栅格个数。
(1)组件配置项
(表 2 – 自适应栅格根底配置项)
以下是容器组件 Grid 的定制配置项,依据栅格个数和限度条件判断是否须要调整栅格个数,进行自适应调整。
(表 3 – 自适应栅格定制配置项)
(2)组件应用范例
这里咱们应用我的项目展现列表来举例。在我的项目展现的场景,咱们将卡片容器应用 Grid 组件,并且在卡片素材应用 GridItem 组件进行包裹,不批改默认的 Grid 参数。
<grid ref="grid" :gridType="'autoMargin'" :baseW="250">
<grid-item v-for="project in projectList"
:key="project.projectId"
class="project-item"
>
<div class="name">{{project.name}}</div>
</grid-item>
</grid>
2、组件外围逻辑
上面简要形容一下栅格布局组件 Grid 的外围逻辑:
- 组件 mounted 后,监听 window 的 resize 事件。
- 页面宽度发生变化时,革除以后计算数据,并从新计算出自适应成果。
- 在组件销毁前,移除对 window 的 resize 事件监听。
mounted () {window.addEventListener('resize', this.calcGridSize, false)
this.reset()},
beforeDestroy () {window.removeEventListener('resize', this.calcGridSize, false)
},
methods: {reset () {
// 革除计算数据
this.calcGridSize()},
calcGridSize () {// 从新进行计算}
}
3、自适应成果计算
不同的自适应计划对应有不同的计算规定,然而其外围计划都是统一的,须要依据三个数值配置项作为基准,求解在页面宽度变动时,其中某一个配置项如何自适应变动。以下整顿三种自适应计划的计算形式:
(表 4 – 自适应栅格实现形式)
以下整顿三种计划的计算公式:
(表 5 – 自适应栅格计算公式)
以下依据自适应卡片宽度为例剖析具体的流程:
- calcGridSize 依据以后配置项抉择计算形式;
- getGridNum 计算出一行同时存在的卡片个数;
- 依据 limitW 计算是否须要调整卡片个数,计算出最终的卡片宽度。
calcGridSize () {
// step 1,抉择计算形式
if (this.gridType === 'autoMargin') {this.calcAutoMg()
} else if (this.gridType === 'autoPadding') {this.calcAutoPd()
} else {this.calcAutoWd()
}
},
// 自适应卡片宽度
calcAutoWd () {
const containW = this.$el.clientWidth
const {baseMg, baseW, limitW} = this
// step 2,计算 grid 个数
const caclW = containW - baseMg
let gridNum = Math.floor(caclW / baseW)
let gridW = caclW % baseW / gridNum + baseW - baseMg
// step 3,修改 grid 个数,计算出最终卡片宽度
if (caclW % baseW > limitW) {gridW = caclW / (1 + gridNum) - baseMg
}
this.gridW = gridW
},
// 自适应外边距
calcAutoMg() {
const containW = this.$el.clientWidth
const {baseMg, baseW, limitMg} = this
// step 2,计算 grid 个数
const caclW = containW - baseMg
let gridNum = Math.floor(caclW / baseW)
let gridMg = (containW - baseW * gridNum) / (gridNum + 1)
// step 3,修改 grid 个数,计算出最终外边距
if (gridMg < limitMg) {
gridNum--
gridMg = (containW - baseW * gridNum) / (gridNum + 1)
}
this.gridMg = gridMg;
},
// 容器自适应内边距
calcAutoPd() {
const containW = this.$el.clientWidth
const {baseMg, baseW, limitPd} = this
// step 2,计算内边距
let gridPd = ((containW + baseMg) % (baseW + baseMg)) / 2
// step 3,修改 grid 个数,计算最终内边距
if (gridPd < limitPd) {
gridPd =
(((containW + baseMg) % (baseW + baseMg)) + baseW + baseMg) / 2
}
this.gridPd = gridPd;
}
4、自适应款式传值 – CSS 变量
上一步骤,咱们通过以自适应卡片宽度为例子,计算出来自适应参数后,须要有一种形式来实现 CSS 款式的父子传值。
在基于 vue 的治理后盾我的项目上,咱们有两种实现形式来解决 CSS 款式的父子传值。
- 通过父子组件 props 来传值
- 通过 CSS 变量来传值
思考到 CSS 变量实现形式更加轻量而且兼容性合乎咱们我的项目要求。咱们通过应用 CSS 变量来实现自适应款式传值,上面简要介绍一下 CSS 变量在前端页面中的应用。
(1)申明与应用
申明 CSS 变量时,须要在变量名后面减少两根连词线(–)。变量名大小写敏感,并且变量的值能够是色值、数字和字符串。
应用 CSS 变量时,须要应用 var()函数进行包裹。var()函数默认承受两个参数,第一个参数是前文定义的 CSS 变量,第二个参数是默认值(可不传)。
上面代码展现了如何申明并应用 CSS 变量
- 在 grids 中申明了变量 –gridW,并且在 grid-item 中进行应用。
- 在 grid-item 中应用变量 –gridH 作为高度,如果获取不到,则应用默认值 50px
<style>
.grids {--gridW: 200px;}
.grids .grid-item {width: var(--gridW);
height: var(--gridH, 50px);
}
</style>
(2)作用域与优先级
CSS 变量能够在多个选择器内进行定义和应用,优先级与 CSS 层叠优先级统一,作用范畴则是在变量定义的选择器范畴内均失效。
(3)兼容性
咱们在业务开发中曾经开始应用 CSS 变量了,通过 CanIUse 网站能够看出目前 CSS 变量曾经兼容了泛滥支流浏览器,并且在前文中提到的谷歌 Material Design 计划也是应用 CSS 变量来实现谷歌的栅格布局计划。所以兼容性上,大家能够放心使用。
(图 9 – CSS 变量兼容性)
如果要思考兼容性解决,倡议在应用 CSS 变量时思考下述办法进行兼容。
<style>
.grids .grid-item {
width: 200px;
width: var(--gridW);
}
</style>
(4)款式传值实现
栅格布局组件在父组件上定义卡片宽度,卡片边距。通过 CSS 变量传值给子组件进行应用。
<template>
<div class="grids" :style="{'--gridW': gridW +'px','--gridMg': gridMg +'px','--gridPd': gridPd +'px'}">
<slot></slot>
</div>
</template>
<script>
// ...
</script>
<style lang="less" scoped>
.grids {
overflow-y: auto;
display: flex;
flex-wrap: wrap;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
align-content: flex-start;
padding: 0 var(--gridPd) 0 calc(var(--gridPd) - var(--gridMg));
>>> .grid-item {width: var(--gridW);
margin-left: var(--gridMg);
}
}
</style>
四、小结
咱们从晋升卡片类页面展现成果的诉求登程,历经:
- 以后布局问题剖析
- 行业内布局计划筛选
- 栅格布局计划实现
- CSS 变量优化
等一系列伎俩,摸索出适宜治理后盾的栅布局计划,更好的服务了中台页面的展现场景。悟地面台开发团队将永不止步,继续钻研和思考,为大家带来更多的实战技巧,感谢您的浏览。
悟空流动中台】系列往期精彩文章:
- 《揭秘 vivo 如何打造千万级 DAU 流动中台 – 启航篇》次要为大家讲述 vivo 流动中台的能力与翻新。
- 《悟空流动中台 – 微组件状态治理(上)》介绍了流动页内 RSC 组件之间的状态治理和背地的设计思路。
- 《悟空流动中台 – 微组件状态治理(下)》摸索平台和跨沙箱环境下的微组件状态治理。
- 《vivo 悟空流动中台 - 基于行为预设的动静布局计划》本文以“满屏”场景下的页面布局思考为切入点,以微组件为元素单元,提供了一种新的布局方案设计思路——基于行为预设的动静布局计划,并具体的分享了设计目标及具体实现计划。
- 《vivo 悟空流动中台 – 微组件多端摸索》是基于自助多端扩大,也就意味着多端 微 组件抉择越丰盛,内容越通用,玩法越多样,产品价值也会越高。
- 《vivo 悟空流动中台 – H5 流动加载优化》从进步资源申请速度,资源压缩、缓存、渲染等多种角度登程,寻找悟空流动专题加载优化计划。
- 《vivo 悟空流动中台 – 基于 WebP 的图片高性能加载计划》从技术选型、架构设计到计划落地,全方位的出现悟空流动中台基于 WebP 的图片高性能加载计划。
更多内容敬请关注 vivo 互联网技术 微信公众号
注:转载文章请先与微信号:Labs2020 分割