You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
为了解决早期 Web 页面在手持设备上的显示问题,Apple 在 IOS Safari 中定义了一个 viewport meta 标签,它可以创建一个虚拟的布局视口(layout viewport),这个视口的分辨率接近于 PC 显示器。这样一来,由于两者的宽度趋近,CSS只需要像在PC上那样渲染页面就行,原有的页面结构也基本不会被破坏。
我们前面一直在讨论 Web 页面在移动浏览器上的适配问题,但是如果网页本来就是为移动端设计的,这个时候布局视口(layout viewport)反而不太适用了,所以我们还需要另一种布局视口,它的宽度和视觉视口相同,用户不需要缩放和拖动网页就能获得良好的浏览体验,这就是理想视口(idea viewport)。
我的大部分性能优化工作都集中在 JavaScript 和 CSS 上,从早期的 Move Scripts to the Bottom 和 Put Stylesheets at the Top 规则。为了强调这些规则的重要性,我甚至说过,“JS 和 CSS 是页面上最重要的部分”。几个月后,我意识到这是错误的。图片才是页面上最重要的部分。
图片几乎占了网页流量消耗的 60%,雅虎军规和 Google 都将图片优化作为网页优化不可或缺的环节,除了图片性能优化外,响应式图片无疑带来更好的用户体验。
2011年,Google 发布了 Android 4.0,在经历了 Cupcake,Donut,Froyo 等多个甜品名称版本的迭代后,安卓终结了 Symbian(塞班)的霸主地位,迅速占领了手机市场跃居全球第一。同年,腾讯发布了微信开始进军移动互联网,阿里也在 2013 年宣布 ALL IN 无线,随着智能设备的普及和移动互联网时代的到来,响应式布局这个词开始频繁地出现在 Web 设计和开发领域,作为一名优秀的前端攻城狮,要将极致的用户体验和最佳的工程实践作为探索的目标 ): balabala...
所以,响应式布局,要学。不仅要学,我们还要了解它的前世今生,前置知识,实现手段和原理,以便在实际应用时选取合适的技术方案。
阅读完本文,你将 Get 以下知识点,
响应式设计
著名的网页设计师 Ehan Marcotte 在 2010 年 5 月的一篇名为《Responsive Web Design》的个人文章中,首次提到了响应式网站设计。文中讲到响应式的概念源自响应式建筑设计,即房间或者空间会根据其内部人群数量和流动而变化。
Web 响应式设计的理念与之非常相似,只不过在这里,
我们需要适配的不是建筑,而是 Web 页面。
我们期望页面可以根据用户的设备环境,比如系统,分辨率,屏幕尺寸等因素,进行自发式调整,提供更适合当前环境的阅读和操作体验,对已有和未来即将出现的新设备有一定的适应能力。
这就是响应式设计的理念。那么是否有对应的方法论呢?
别急,在谈及实现之前,我们需要了解一些前置知识,比如像素。
像素
什么是像素?
像素是图像中最小的单位,一个不可再分割的点,对应到物理设备上(比如计算机屏幕),就是屏幕上的一个光点。我们常说的分辨率就是长和宽上像素点的个数,比如 IPhone X 的分辨率是 1125×2436,代表屏幕横向和纵向分别有 1125 和 2436 个像素点,这里的像素是设备像素(Device Pixels)。
1px ≠1像素
实际开发中,你可能发现 Iphone X 的设计稿是 375×812,WTF?
这里的 375×812 是 CSS 像素,也叫虚拟像素,逻辑像素。为什么我们不使用设备像素呢?
设备像素对应屏幕上的光点,如今的屏幕分辨率已经达到人眼无法区分单个像素的程度了。试想一下,要在 IPhone X 宽不到 7cm 的屏幕上数出 1125 个像素点,想想就让人头疼。所以我们在实际开发中通常使用 CSS 像素,你眼中的 1px 可能对应多个设备像素,比如上面的 IPhone X,
而上面这个比值 3 就是设备像素比(Device Pixel Ratio,简称 DPR)。
DPR 可以在浏览器中通过 JavaScript 代码获取,
像素是一个固定单位,一般我们不会使用固定像素来做响应式布局,但是你需要了解他。相反,响应式布局里经常会用到相对单位,比如 EM。
EM
EM 相对于元素自身的
font-size
,如果元素没有显式地设置
font-size
,那么1em
等于多少呢?这个问题其实跟咱说的
em
没啥关系,这里跟font-size
的计算规则相关,回顾一下。如果元素没有设置font-size
,会继承父元素的font-size
,如果父元素也没有,会沿着 DOM 树一直向上查找,直到根元素html
,根元素的默认字体大小为 16px。理解了
EM
,REM
就很简单了。REM
REM = Root EM,顾名思义就是相对于根元素的 EM。所以它的计算规则比较简单,
1
rem
就等于根元素html
的字体大小,所以,如果我们改变根元素的字体大小,页面上所有使用
rem
的元素都会被重绘。EM 和 REM 都是相对单位,我们在做响应式布局的时候应该如何选择呢?
根据两者的特性,
html
的字体大小,所以 REM 的使用更加广泛一些实际开发中,设计图的单位是 CSS 像素,我们可以借助一些工具将 px 自动转换为 rem,
下面是一个用
PostCSS
插件在基于 Webpack 构建的项目中自动转换的例子,我们已经有响应式单位了,接下来要怎么让页面支持响应式布局呢?
第一步需要先设置页面的
viewport
。Viewport
著名的 JavaScript 专家 Peter-Paul Koch 曾发表过三篇有关
viewport
的文章,建议先看完上述文章。
viewport
最先由 Apple 引入,用于解决移动端页面的显示问题,通过一个叫<meta>
的 DOM 标签,允许我们可以定义视口的各种行为,比如宽度,高度,初始缩放比例等,Peter-Paul Koch 在文章中将移动浏览器的视口分为三种。
layout viewport
为了解决早期 Web 页面在手持设备上的显示问题,Apple 在 IOS Safari 中定义了一个
viewport meta
标签,它可以创建一个虚拟的布局视口(layout viewport
),这个视口的分辨率接近于 PC 显示器。这样一来,由于两者的宽度趋近,CSS只需要像在PC上那样渲染页面就行,原有的页面结构也基本不会被破坏。layout viewport
是一个固定的值,由浏览器厂商设定,可以通过
document
获取布局视口的宽度和高度,visual viewport
视觉视口(visual viewport)可以简单理解为手持设备物理屏幕的可视区域。也就是你的手机屏幕,所以不同设备的视觉视口可能不同,有了
visual viewport
,我们就可以实现网页的拖拽和缩放了,为什么?因为有了一个承载布局视口的容器。
试想一下,假如我们现在有一台 IPhone 6(375×627),它会在宽为 375px 的
visual viewport
上,创建一个宽为 980px 的layout viewport
,于是用户可以在visual viewport
中拖动或缩放网页来获得更好的浏览体验。视觉视口可以通过
window
获取,idea viewport
我们前面一直在讨论 Web 页面在移动浏览器上的适配问题,但是如果网页本来就是为移动端设计的,这个时候布局视口(layout viewport)反而不太适用了,所以我们还需要另一种布局视口,它的宽度和视觉视口相同,用户不需要缩放和拖动网页就能获得良好的浏览体验,这就是理想视口(idea viewport)。
我们可以通过
meta
设置将布局视口转换为理想视口,meta
视口可以通过
<meta>
进行设置,viewport
元标签的取值有 6 种,了解了视口之后,让我们回到响应式布局,与视口相关的几个单位有:vw,vh,百分比。
vw,vh,百分比
浏览器对于
vw
和vh
的支持相对较晚,在 Android 4.4 以下的浏览器中可能没办法使用,下面是来自 Can I use 完整的兼容性统计数据,新生特性往往逃不过兼容性的大坑,但是这并不妨碍我们了解它。
响应式设计里,
vw
和vh
常被用于布局,因为它们是相对于视口的,以 IPhone X 为例,vw 和 CSS 像素的换算如下,
我们说百分比也可以用来设置元素的宽高,它和
vw
,vh
的区别是什么?这里只需要记住一点,百分比是相对于父元素的宽度和高度计算的。
到这里,相信你已经掌握了响应式布局里常用的所有单位。接下来,我们介绍弹性盒和栅格,它们都不是单位,而是一种新的布局方案。
弹性盒
W3C 在 2009 年提出了弹性盒,截止目前浏览器对
FlexBox
的支持已经相对完善,下面是 Can I use FlexBox 完整的兼容性情况,关于弹性盒模型推荐阅读这篇文章 A Complete Guide to Flexbox。
假设你已经阅读完并了解了弹性盒模型,响应式布局中我们需要关注
FlexBox
里的两个角色:容器和子元素。container
指定
display
属性为flex
,就可以将一个元素设置为FlexBox
容器,我们可以通过定义它的属性,决定子元素的排列方式,属性可选值有 6 种,items
子元素也支持 6 个属性可选值,
弹性盒模型布局非常灵活,属性值也足够应对大部分复杂的场景,但
FlexBox
基于轴线,只能解决一维场景下的布局,作为补充,W3C 在后续提出了网格布局(CSS Grid Layout),网格将容器再度划分为 “行” 和 “列”,产生单元格,项目(子元素)可以在单元格内组合定位,所以网格可以看作二维布局。网格
关于网格布局推荐阅读这篇文章 A Complete Guide to Grid。
上述文章非常详细地介绍了网格的一些基本概念(比如容器和项目,行和列,单元格和网格线等),使用姿势,注意事项等。作为新兴的布局方案,使用时你需要考虑兼容性是否满足,
不过在标准之外,我们可能也正通过其他的一些姿势在使用网格。如果你关注时下一些比较热门的 UI 库,比如 Ant Desgin,Material UI,Element Plus 等,它们以栅格系统的方式实现了对网格部分特性的支持。
UI 库对
Grid
的实现中,通常会使用到媒体查询,这也是响应式布局的核心技术。媒体查询
媒体查询(Media Query)是 CSS3 规范中的一部分,媒体查询提供了简单的判断方法,允许开发者根据不同的设备特征应用不同的样式。响应式布局中,常用的设备特征有,
min-width
时应用样式max-width
时应用样式portrait
|landscape
,当前设备的方向选择
min-width
和max-width
取值的过程,称为设备断点选择,它可能取决于产品设计本身,下面是 百度 Web 生态团队 总结的一套比较具有代表性的设备断点,如果你需要对细分屏幕大小进行适配,ResponsiveDesign 站点上的这篇文章 Media queries for common device breakpoints 可能会有所帮助。
响应式文字和图片
相信你已经掌握了响应式布局的所有知识,接下来我们介绍一些最佳实践。
文字
大多数用户阅读都是从左到右,如果一行文字太长,阅读下一行时容易出错,或者用户只会读一行文字的前半部分,而略读后半部分。在上世纪就有研究表明,一行 45 ~ 90 个英文字符是最好的,对于汉字来说,一行文字合理的数量应该是 22 ~ 45 个字符。
此外,字体大小对阅读体验同样重要,基本字体一般不小于
16px
,行高大于1.2em
。图片
《高性能网站建设指南》的作者 Steve Souders 曾在 2013 年的一篇 博客 中提到:
图片几乎占了网页流量消耗的 60%,雅虎军规和 Google 都将图片优化作为网页优化不可或缺的环节,除了图片性能优化外,响应式图片无疑带来更好的用户体验。
下面是一些响应式图片的最佳实践,
1.确保图片内容不会超出 viewport
试想一下,如果图片固定大小且超出理想视口的宽度,会发生什么?
内容会溢出视口外,导致出现横向滚动条对不对,这在移动端是非常不好的浏览体验,因为用户往往更习惯上下滚动,而不是左右滚动,所以我们需要确保图片内容不要超出
viewport
,可以通过设置元素的最大宽度进行限制,类似的,相同的规则也应该用于一些其他的嵌入式元素,比如 embed,object,video 等。
2. 图片质量支持响应式
这是一种支持优雅降级的方案,现代浏览器已经支持了
srcset
和sizes
属性,对于兼容性不好的浏览器,会继续使用默认src
属性中的图片,所以我们可以放心大胆的使用。如果我们书写了上面代码中的图片,浏览器会根据下面的顺序加载图片,
srcset
中最接近这个尺寸的图片并显示除了上述方式外,我们也可以使用
HTML5
标准中的picture
标签实现类似的效果,小结
我们从响应式布局的设计角度出发,介绍了响应式的设计理念,前置知识(像素,DPR,视口等),相对单位(em,rem,百分比,vw,vh等),布局方案(FlexBox,Gird)以及媒体查询等技术,其中不乏很多前辈们的最佳实践,作为开发者我们应该用这些经验,以更好地优化不同尺寸大小设备的用户体验。
参考链接
写在最后
本文首发于我的 博客,才疏学浅,难免有错误,文章有误之处还望不吝指正!
如果有疑问或者发现错误,可以在相应的 issues 进行提问或勘误
如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励
(完)
The text was updated successfully, but these errors were encountered: