现代网站都需要各种布局以保证页面展示效果,本文就说说布局
布局类型
视觉类型
不同布局看起来的效果不一样
主要有 3 种
- 两栏布局,很少单独使用了,一般用在给三栏布局的中间部分做两栏布局
- 三栏布局(多栏布局同三栏思路),如淘宝首页,两侧留空,中间保有内容
- 平均布局,如淘宝首页下方的 猜你喜欢,平均排列各种商品
技术类型
可以选用不同的方案实现布局
主要有 4 种
- 纯文档流布局
- float 浮动布局
- flex 弹性盒子布局
- grid 网格布局
本文以技术类型为轴,分别尝试实现 3 种视觉类型
本文中的两栏布局采用如下设计图
如图,画得不太准,认为是方形就好了,同时为了展示效果,在代码中会放大 10 倍
三栏布局采用 淘宝首页 作为示例
平均布局采用 bilibili 番剧区作为示例
纯文档流
纯文档流布局,利用了文档流本身的特点——表现为块级的元素逐行排列,表现为内联的元素同行自左向右排列
两栏布局
由图片可得,大致有如下结构的 HTML
1 | <body> |
使用如下 CSS,即可完成两栏布局
1 | * { |
效果如图
三栏布局
显然只需要在 body 中放置 3 个块
于是可以推出如下 HTML
1 | <body> |
使用如下 CSS,即可完成三栏布局
1 | * { |
效果如图
可见随着视口变小,中间部分也会自适应
平均布局
平均布局一般都设定了每个单位所占大小,所以一般分为占满全行和占不满两种
而占不满的话,在多行场合下末行又会很难看,所以一般都是占满全行
设每个块大小为 width = height = 200px,每行 4 个块,放在刚才的三栏布局的 main 元素中
那么显然,为了维持每行 4 个块,应该取消响应式
鉴于之前说过的 margin 的同行不合并特性,一般只会设置单方向(通常为 right)的 margin
设每两个块之间隔开的距离为 x,显然 4 200px + 3 x = main.width - main.border.width * 2
设 x = 30px,则 main.width = 892px
可以推出如下 HTML
1 | <body> |
使用以下 CSS,即可实现占满全行的效果
1 | /* reset */ |
效果如图
发现惨了!怎么换行了!
从开发者工具可以看到,是因为每行最后一个 div 的右外边距超出容器了,所以被换行,这时候,我们需要添加如下 CSS
1 | /* reset */ |
或选用对容器进行调整的 CSS,更高级,更受面试官喜爱
1 | /* reset */ |
效果如图
但是现在纯文档流布局已经没人用了,除非你的网站需要在 IE 6 以下运行……
float
通过 caniuse,我们知道对于 IE,float 可以运行在 IE 6 7 8 9 10 11 上,除非 6 以下才需要使用纯文档流布局
而 flex 在 IE 6 7 8 9 上都不能使用,10 和 11 的兼容性也不是完全兼容
所以,假如你还需要兼容 IE,最好使用 float 布局
两栏布局
由图片可得,大致有如下结构的 HTML
1 | <body> |
使用如下 CSS,即可完成两栏布局
1 | * { |
效果图与纯文档流相同
从 CSS 可见,如果同层级的两个元素都是向左浮动的话,则排列顺序按照其在文档中的出现顺序
当然也可以令右边盒子向右浮动,此时右边盒子会出现在父元素的最右边,具体位置取决于父元素宽度
在本例中,如果父元素宽度为 800px,则与向左浮动表现相同
三栏布局
显然只需要在 body 中放置 3 个块
于是可以推出如下 HTML
1 | <body class="clearfix"> |
使用如下 CSS,即可完成三栏布局
1 | /* reset */ |
效果图与纯文档流相同
平均布局
float 实现平均布局的代码和效果,与纯文档流几乎一致,除了 clearfix
,就只是把
1 | display: inline-block; |
换成了
1 | float: left; |
而已
关于右外边距溢出容器的处理,也与纯文档流一致
故此处不再给出示例
flex
通过 caniuse 可以发现,除了 IE 之外的所有浏览器最新版本均支持 flex,但 grid 布局尚未受到全面支持
所以当你不需要兼容 IE,但又不是只需要兼容最新的浏览器时,可以选择 flex 布局方案
附一个 flex 布局小游戏
语法
flex 有两个主要概念:容器(container)和项目(item)
一个容器中包含两条轴:主轴和交叉轴,交叉轴恒垂直于主轴。默认主轴是水平方向
一个容器中往往包含多个项目,项目沿主轴排列
容器
容器上可以设置 6 个属性
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
属性含义不解释了,本文不是教语法的,是教布局的,可以点击阮一峰博客学习语法
下同,不讲语法
项目
项目上可以设置 6 个属性
- order
- flex-grow
- flex-shrink
- flex-basis
- flex
- align-self
两栏布局
显然扭转主轴方向到竖直方向,更有利于排版
所以由图片可得,大致有如下结构的 HTML
1 | <body> |
使用如下 CSS,即可完成两栏布局
1 | /* reset */ |
效果图与纯文档流相同
三栏布局
显然只需要在 body 中放置 3 个块
于是可以推出如下 HTML
1 | <body> |
使用如下 CSS,即可完成三栏布局
1 | /* reset */ |
效果图与纯文档流相同
代码明显比 float 简洁许多,所以是比 float 更好用的布局方案
平均布局
设每个块大小为 width = height = 200px,每行 4 个块,放在刚才的三栏布局的 main 元素中
可以推出如下 HTML
1 | <body> |
使用以下 CSS,即可实现占满全行的效果
1 | /* reset */ |
效果如图
发现,坏了,怎么最后一行隔开这么远
于是我们便不能使用 justify-content
来简单控制间距,必须使用 margin-right
来控制
计算结果沿用纯文档流布局的计算结果
于是 CSS 变更为如下
1 | /* reset */ |
效果如图
好了,使用负 margin,成功修复!
当然 nth-child 也可以,不过不建议
grid
通过 caniuse 可以发现,grid 布局尚未受到全面支持
所以当你只需要兼容最新的,甚至是未来的浏览器时,可以选择 grid 布局方案
附一个 grid 布局小游戏
语法
容器和项目的概念同 flex,但是 grid 没有主轴和交叉轴
如果说 flex 的精力集中在每个容器的主轴上,是一维操作,那 grid 布局就是二维操作
容器
容器上可以设置 7 种属性
grid-template-columns/rows/areas
column/row-gap
gap
grid-auto-flow
justify/align/place-items
justify/align/place-content
grid-auto-columns/rows
项目
项目上可以设置 3 种属性
- grid-column/row-start/end
- grid-column/row/area
- justify/align/place-self
两栏布局
由图片可得,大致有如下结构的 HTML
1 | <body> |
使用如下 CSS,即可完成两栏布局
1 | /* reset */ |
效果图与纯文档流相同
语义化非常好,一看就知道布局长什么样
三栏布局
显然只需要在 body 中放置 3 个块
于是可以推出如下 HTML
1 | <body> |
使用如下 CSS,即可完成三栏布局
1 | /* reset */ |
效果如下
这令人惊叹的高度语义化,比 flex 高到不知道哪去了
平均布局
设每个块大小为 width = height = 200px,每行 4 个块,放在刚才的三栏布局的 main 元素中
可以推出如下 HTML
1 | <body> |
使用以下 CSS,即可实现占满全行的效果
1 | /* reset */ |
效果如图
完美的自动占格子,不再有负 margin 的问题
即便需要间隔,也可以通过 gap 来实现
1 | /* reset */ |
效果如图
天不生我 grid 布局,万古如长夜!!!