HTML 布局
页面布局管的是文本、图像和块在页面上怎么摆、占多大。屏幕一变,有的方案只改尺寸、不改结构,有的只在几个断点上换结构,有的两者一起变。选哪一种,先看设计要不要跟着视口改版,再看尺寸要不要跟着视口伸缩。
响应式布局和其他条目不同:它是一套设计目标和技术统称,不是某一种 CSS 写法。
静态布局(px 布局)
传统 Web 布局,网页上的所有元素一律使用 px 作为单位。
布局特点:任何屏幕分辨率下,页面元素的布局和大小都不会变化,网页始终按照最初写代码时的布局来显示。
设计方法(常规 PC 端):
页面内容居中布局,所有样式使用绝对宽度、高度(px)。如果屏幕宽度小于页面内容宽度就会出现滚动条,如果大于这个宽度则内容居中,外侧铺背景。
设计方法(移动端,会改变元素大小):
在
viewport的meta上设置width=320,页面的各个元素也采用px作为单位。再用 JavaScript 动态修改initial-scale,让页面等比缩放,刚好占满整个屏幕。<meta name="viewport" content="width=320, initial-scale=1, user-scalable=no, viewport-fit=cover">在
viewport的meta上设置width=640, user-scalable=no,页面的各个元素也采用px作为单位。由于640px超出了手机宽度,浏览器会自动缩小页面至刚好全屏。<meta name="viewport" content="width=640, user-scalable=no, viewport-fit=cover">
user-scalable=no 会禁止用户捏合缩放,损害无障碍。若只是为了定宽缩放,应评估是否必须关掉缩放。
优点:对设计师和 CSS 编写者来说都最简单。纯 px 静态页兼容负担小。
缺点:不能根据用户的屏幕尺寸做出不同的表现。靠改 viewport 去「撑满屏幕」的那套,各机缩放比例和 1px 发虚要自己测。
流式布局(百分比布局)
流式布局使用百分数(常搭配 min-*、max-*)为单位定义元素的宽度。页面元素的宽度按照屏幕分辨率进行适配调整,但整体布局不变。
布局特点:屏幕分辨率变化时,页面元素的大小会变化但布局不变。
设计方法:使用百分比定义宽度,高度大都还是用 px。宽度往往配合 max-width、min-width 等属性控制尺寸流动范围,以免过大或过小影响阅读。
缺点:宽度会按照屏幕进行适配调整,但高度不会。屏幕相对原始设计过大或过小时,体验不好:有些元素的宽度过大或过小,和固定大小的高度、文字会显得不协调。
自适应布局(@media 布局)
用 @media 为不同的屏幕分辨率定义布局,即创建多个静态布局,每个静态布局对应一个屏幕分辨率范围。改变屏幕分辨率可以切换不同的静态布局(元素布局会发生变化),但在每个静态布局中,页面元素大小不随窗口大小的调整发生变化。
布局特点:屏幕分辨率变化时,页面元素的布局会变化但大小不变。
设计方法:使用 @media 加上 min-width、min-height 等,给不同尺寸和介质的设备切换不同的样式。在断点设计得当的前提下,适配范围内的设备体验最好;在同一个断点区间里,实际仍是固定布局。
缺点:媒体查询是有限的,可以枚举出来,只能覆盖主流宽高。要匹配足够多的屏幕大小,工作量不小,设计也需要多个版本。
这里的「自适应」是中文前端里相对「响应式」的习惯用法:多套定宽(或定布局)在断点处切换。和英文文献里 Adaptive Design 的细节并不一一对应。
响应式布局(综合布局)
响应式布局不是单独的技术,它是描述 Web 设计的一种方式、一组实践,目标是让同一个页面在各种终端上(各尺寸的 PC、手机、手表、以至冰箱上的 Web 浏览器)都能得到可接受的呈现。
它不是某一种具体的布局写法,通常糅合流式布局、自适应布局,以及 rem、em、flex、grid、vw、vh 等技术。常见做法是:用 @media 为不同屏幕分辨率定义布局,每个布局再用流式、弹性、vw、vh 等实现。
现行面向多端的页面,默认按响应式来做。
布局特点:屏幕分辨率变化时,页面元素的布局和大小都会变化。
设计方法:通常使用 @media 为不同屏幕分辨率定义不同布局,用流式布局、flex、grid 配合相对单位来排。凡是有助于同一份网页在不同设备上呈现更好画面的技术都可以纳入。
优点:能同时照顾 PC 和移动端。做得足够细,各端都能对齐各自的设计。
缺点:屏幕分辨率不同的设备越来越多,开发和测试的工作量不小,设计稿也需要多个版本。
弹性布局
弹性布局的概念并不统一,已知有三种说法:
- 指
rem、em布局 - 指
flex布局 - 认为弹性布局只是实现响应式的一部分,不应单独算作一种布局形式
实务里也常把 grid 和 flex 一起算进弹性实现:flex 管一维,grid 管二维。
rem、em 布局
使用 rem、em 单位进行相对布局。rem 相对 <html>(根元素)的字体大小;em 相对父元素的字体大小。它们随字体大小变化。与百分比相比,rem、em 更灵活,能用在缩进、字体大小、padding、margin 以及元素宽高等多种属性上。
布局特点:元素采用 em、rem 为单位,在不同屏幕分辨率下,页面元素的大小会等比例缩放但布局不变。
设计方法:以 em 为单位时,多层嵌套后最终计算值不好控。所以弹性布局多用 rem。1rem 等于根元素的 font-size,浏览器默认多为 16px。页面元素用 rem,根元素字号一变,元素跟着缩放。
实际应用中,可以根据屏幕尺寸,用 JavaScript 修改根元素的字体大小:
// 以 375px 为基准,根据屏幕宽度调整根节点 fontSize,最大不超过 32px。
document.documentElement.style.fontSize = `${Math.min(16 * document.documentElement.clientWidth / 375, 32)}px`
优点:各屏幕的高宽比和最初设计接近时,缩放最整齐。
缺点:算出来的值常带小数,在部分机型上会碰到亚像素舍入引起的缝、错位。
也可用 vw 直接设根字号(如 html { font-size: 4.26666667vw } 对应 375 设计稿下 1rem = 16px),不必每次都跑这段脚本。
flex 布局
目前常用的一维布局。传统的浮动、定位很难做的对齐、剩余空间分配,用 flex 就容易很多。
优点:写法短,能力完整,容易做成可随视口调整的布局。适合导航、工具条、沿一条轴分布的组件。
缺点:IE 9 及更早没有 flex;IE 10 是旧语法,IE 11 仍有不少 bug。现行主流浏览器都支持。flex 管的是轴上的排列和分配;元素自身宽高随视口变,仍要靠相对单位或媒体查询另做。整页分栏、卡片矩阵这类二维结构,更适合下面的 grid。
grid 布局
网格布局(CSS Grid)按行和列同时排。容器设 display: grid 后,用 grid-template-columns、grid-template-rows、gap 以及 fr、minmax()、auto-fill、auto-fit 等,把子项放进格子,也能让某一项跨行、跨列。
布局特点:屏幕变宽时,格子可以增多、变宽,或按媒体查询换成另一套轨道;结构是二维的,不需要靠多层 flex 去「模拟」行列。
设计方法:整页骨架(页头、侧栏、主区、页脚)和等宽卡片墙用 grid;格子内部的一排按钮、标题和操作仍用 flex。响应式里常见 repeat(auto-fill, minmax(16rem, 1fr)) 这类写法,视口变宽自动加列,而不必先写死列数。
优点:行列一起声明,对齐和间距(gap)比浮动、多栏 flex 更稳;fr 按剩余空间分配轨道,和 flex 的 flex-grow 类似,但面向的是整张网。
缺点:IE 不支持现行 grid(IE 11 的 -ms-grid 是另一套)。现行主流浏览器都支持。只做一条轴上的分布时,grid 往往不如 flex 省事。
和 flex 的分工:一条轴、内容多少不定,用 flex;既要行又要列、要跨格,用 grid。两者经常叠在同一套响应式页面里。
常见问题
响应式与自适应布局有什么区别?
自适应:当屏幕尺寸变小时,内容的布局会发生变化,比如由一行展示变为分行展示。而内容的大小、宽高不会随着尺寸变化而实时改变(只在断点处切换另一套固定布局)。
响应式:当屏幕尺寸变小时,内容的布局会发生变化,比如由一行展示变为分行展示。而内容的大小也会随着尺寸变化而实时变化。
vw 和 vh 是什么?
vw 和 vh 是视口单位。相对的是浏览器视口(layout viewport)的尺寸,不是显示器标称的物理分辨率。
vw:相对视口宽度。视口宽度是100vw,1vw等于可视窗口宽度的百分之一。vh:相对视口高度。视口高度是100vh,1vh等于可视窗口高度的百分之一。vmin:vw和vh中较小的那个。vmax:vw和vh中较大的那个。
vw、vh 和 rem 经常一起用,覆盖宽度伸缩和根字号缩放。
另有 vi、vb、svh、lvh、dvh 等,用来处理书写方向和移动端工具栏引起的视口跳动。需要时再查长度单位专篇。
如何选择布局方式?
- 如果只做 PC 端,那么静态布局(定宽度)是最省事的选择。
- 如果做移动端,且设计对高度和元素间距要求不高,那么弹性布局(
rem、flex或grid)是合适的选择。 - 如果 PC、移动要兼容,而且要求高,那么响应式布局仍是正选:设计按不同宽高出多稿,实现上用媒体查询切换布局,再用流式或相对单位处理尺寸。
结语
面向单端时,把尺寸钉死或按一种相对单位缩放即可;面向多端时,用媒体查询换结构,用相对单位和一维、二维布局模块管分配。手段可以叠用,目标是同一份页面在各终端都站得住。