前言
相信大家都能够轻松的编写上面布局的代码
如果是下面的布局呢?你会怎么样编写?
它们的2栏和3 栏 布局是相似的。只是列的宽度不一样。
我们可能就会 复制同样的代码,然后修改宽度。来扩展 成为 不同的布局。
这样的方式很容易出错,扩展性、复用性也较差。
有没有一种设计方法,可以让我们灵活的快速的生成我们所需要的布局。
当然有,
css网格系统(栅格系统)
运用固定的格子,遵循一定的规则,进行页面的布局设计,使布局规范简洁有规则
它存在于很多的框架 和组件当中。相信大家都有用过。也感受到了网格系统的强大。
它把页面等分为 8列 、12列 、或者24列(至于为什么是8列、12列 、或者24列,大家可以参阅 网格设计规范)
我们可以在此基础上 通过 组合 不同的列 来 衍生出 很多不同的排版方案。非常灵活,具有很高的延展性。
实现1个网格系统,我们可以基于 float 、flex 或者 grid 当中的其中一种排版技术就可以。
我们主要是讲解 基于 flex的 网格系统
网格的基础概念
网格宽度
这里我们不采用固定的宽度,而是100%。如果你需要固定的宽度,可以外层加一个容器。
列数
将整个网格宽度 等分为 多少列 (100% / 24) 。这里我们基于24列
列宽和间隔
列宽
- 网格列宽: 整个网格等分之后每一列的宽度
- 内容列宽: 一块内容通常会占用1个或者多个列的宽度,我们把这个区域理解为内容区域,用于承载一个区域的内容。
间隔(gutter)
- 列与列之间的距离
占据1个网格列宽的内容列宽
占据2个网格列宽的内容列宽
计算列宽
eg: 网格宽度 960px, 等分分为12列
网格列宽: 960 / 12 = 80
内容列宽 :
- 如果间隔为0: 内容列宽 = 网格列宽
- 如果间隔不为0 (gutter = 20)
- 由于使用 flex 的 属性gap 设置间距,最后一个列右侧是没有间距的。所以会有20的剩余空间,flex 会把剩余的空间 平均分配到网格的粉色区域上。粉色区域主要是承载内容的。所以也叫内容区域。
- 内容列宽为: (网格列宽 - 间隔) + 间隔/12 = 61.66
从上面可以看出 内容列宽 是基于网格列宽计算的
通常内容列宽是占有1个或者多个网格列宽
如果内容列宽占1个网格列宽(1个网格列宽为80, 粉色区域 + 间隔 = 81.66)
是下面这样占据的, 间隔处还有剩余1.66的空间。
而内容列宽是粉色的区域 不应该包含右侧的占据已有的间隔(此时并没有完全占有间隔,间隔还有1.66的空间)
如何计算内容的列宽呢?
内容列宽 = 网格列宽 - 占据的间隔宽度
占据的间隔宽度 = 间隔宽度 - 间隔宽度 / 12
所以
- 占据1个网格列宽的内容宽度 = 网格列宽 - (间隔 - 间隔/12)
- 占据2个网格列宽的内容宽度 = 网格列宽 * 2 - (间隔 - 间隔/12 * 2) ...
- 占据12个网格列宽的内容宽度 = 网格列宽 * 12 - (间隔 - 间隔/12 * 12) = 网格宽度 * 12
那么有么有更好的容易理解的计算方法呢?
我们只需要把网格列宽 从原来的80 变为 81.66
那么1个网格列宽正好就是 内容列宽+ 间隔
- 占据1个网格列的内容列宽 = 网格列宽 - 间隔
- 占据2个网格列的内容列宽 = 网格列宽 * 2 - 间隔
- 占据3个网格列的内容列宽 = 网格列宽 * 3 - 间隔
......
这样计算是不是更容易呢?
问题来了
那怎么 把 网格列宽 从80 变成81.66呢?
这多出1.66 正好是 间隔20 等分12 的值。
那是不是把 网格宽度 + 1个间隔的距离 再等分12 就变成81.66呢?
所以网格列宽 计算方式从原来的 960 / 12 变为 (960 + 20 ) / 12
你可能会疑惑 网格宽度在增加20 不就变成 980呢。会不会多出 20的空间?
答案是 不会的。接下来,我们来推导一下。
eg:
- 内容列宽 占 1个网格列宽,那么 就是 ( 960 + 20)/ 12 - 20
- 内容的宽度 占 2列,那么 就是 ((960 + 20)/ 12) * 2 - 20
以此类推
.......
如果内容列宽所占的网格列包含最后一个网格列呢?
eg:
内容宽度 占据12个网格列宽
内容宽度 = (960 + 20) / 12 * 12
你会发现内容列宽变成了980了,也就是超出了网格宽度
而内容列宽 是不占据最右侧那多出来的空间的
我们把内容列宽减去20 是不是正好和网格宽度增加的20 相互抵消了呢?
也满足了我们12列所占的内容宽度为960了。
这样不管占据多少网格列的内容列宽计算公式是不是就一致了呢?
计算公式
-
网格列宽 = (网格宽度 + 间隔) / 列数
-
占据N个网格列宽的内容列宽 = 网格宽度 * N - 间隔
理解了这些概念之后, 下一节我们将用具体的代码来实现。