作者 | Brilliant Open Web团队

编辑 | Aaron

本文承接上一章的内容,接着介绍响应式布局设计,主要讲如何实现响应式图片。通过对图片适配问题的说明,加深对响应式图片的理解,并分析对比了响应式的使用场景以及实现方法,以选择合适的方案让图片更好地适配不同的设备。

图片在 Web 中占有非常重要的地位,一方面,一图胜千言,图片作为内容的载体,能够有效传递出信息;另一方面,图片占网页流量消耗的 60%,对网页的大小和加载速度有很大的影响。

随着终端设备日益丰富,人们更多地通过各种尺寸的小屏浏览网页,经常发生图片过大导致网页布局混乱的情况,非常影响用户体验。因此图片需要根据设备类型和尺寸进行自适应调整,才能保证网站在各个终端获得相似的使用体验。

要做到图片自适应宽度,一个简单的方法是,给图片设置 max-width: 100%,这确实非常有作用,图片不会溢出或者页面出现横向滚动条,那还有没有其他需要我们注意的呢?

(图片来源:http://www.108themes.com/windows-10-themes/italy/)

图片的质量

在使用高清屏幕设备(比如 iPhone X)浏览网站时我们会发现,一些图片看起来比较模糊,而在普通屏幕设备中却没有那么模糊,这是为什么呢?

这里需要用到在上一章中提到的几个概念,为方便起见,我们一起来回顾一下:

物理像素(设备像素)

一个物理像素代表的就是最小的物理显示单元,在同一个设备中,物理像素点的大小是固定的,数量也是固定的。比如 iPhone X 的物理像素是 1125x2436。

逻辑像素(CSS 像素、设备独立像素)

逻辑像素是一个抽象单位,与设备无关,在不同的设备中呈现的大小是一致的,比如逻辑像素为 10x10 的方块,在手机和显示器看上去大小是一样的,这样可以保持阅读体验的一致,同时也方便开发。iPhone X 的逻辑像素是 375x812。

设备像素比(Device Pixel Ratio,DPR)

根据以上两个概念,可以自然地想到,在一个设备中逻辑像素与物理像素的比值是确定的,一个逻辑像素覆盖了多个物理像素,这可以用设备像素比来表示。比如 iPhone X,375x812 的逻辑像素包含了 1125x2436 的物理像素,设备像素比的值就是 3。可以通过下图进一步理解上面三个概念之间的关系。

有了上面的概念,就能简单地解释图片为什么会变模糊。举个例子,分别在普通屏(DRP = 1)和 Retina 屏(DPR = 2)用 CSS 像素为 300x400 的  显示分辨率是 300x400 的图片。

对于普通屏,图像像素和物理像素 1:1,图像不失真。而对于 Retina 屏,图像像素和物理像素 1:4,由于每个图像像素不可分割,物理像素就近取色,从而让图片变得模糊。这种情况需要使用分辨率更高的图片,比如分辨率为 600x800,图像像素和物理像素 1:1,这样就能充分利用 Retina 屏幕的物理像素点,显示出更清晰的图片。

如果在普通屏下也使用分辨率为 600x800 的图片,图像像素和物理像素 4:1,物理像素点只能通过采样,用不足的数量来显示图片。这不仅没有发挥出高清图片的优势,还由于图片的增大而造成了带宽的浪费。

由此可以发现,为了更好地在各种终端设备显示图片,需要考虑设备像素比、图像分辨率、渲染尺寸等因素,如果只是简单地加载图片然后修改样式适应宽度,并不能保证显示效果和加载速度,甚至会大大降低用户的使用体验。因此,需要采用合适的方法对图片进行响应式设计。

媒体查询(media query)

根据前面的分析,图片的响应式设计与渲染尺寸(图片显示大小, 的 CSS 像素)有关,而渲染尺寸通常由设备的视口大小决定,因此就需要一种方法对设备的视口大小进行判断。

CSS 中的媒体查询提供了相关的判断方法,可以根据不同的设备特征应用不同样式。媒体查询支持很多设备特征,由于本章主要介绍响应式图片,实际主要用到其中的视口的宽度和设备方向,如下表所示。

更多关于媒体查询的介绍可以参考 MDN 上的文档《CSS 媒体查询》(https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Media_queries)。

设备特征 取值 说明
min-width 数值,如 600px 视口宽度大于 min-width 时判断为真
max-width 数值,如 800px 视口宽度小于 max-width 时判断为真
orientation portrait | landscape 当前设备方向,portrait 垂直,landscape 水平

对于 min-width 和 max-width 的取值,我们称为断点(Breakpoints)。如何选择断点,主要取决于产品设计本身,没有万能媒体查询的代码。但经过实践,我们也总结了一套比较具有代表性的设备断点。

如果要对细分屏幕大小进行适配,可以查看这篇文章,里面列出了详细的常见设备的媒体查询条件,《media queries for common device breakpoints》(https://responsivedesign.is/develop/browser-feature-support/media-queries-for-common-device-breakpoints/)。

实现响应式图片

前面说了这么多,终于到大家最为关心的部分了。不过先别急,在动手之前,还有一个问题是需要我们去思考的,那就是在根据设备特征选用不同的图片时,是否需要更改比例、裁剪甚至替换整个图片,或者只是仅仅更改图片的分辨率。前者被称为艺术方向(art direction),后者被称为分辨率切换(resolution switching),下面先介绍分辨率切换。

分辨率切换

分辨率切换主要用于优化低分辨率设备的带宽消耗,通常使用在如下场景:开发者提供图片的多个分辨率版本,大屏和高清屏用户获取高分辨率版本,小屏用户获取低分辨率版本。以下是实现分辨率切换的代码例子:

<img srcset="1200x800.jpg 1200w,             700x500.jpg 700w,             500x400.jpg 500w,             300x200.jpg 300w"     sizes="(max-width: 480px) 350px, (max-width: 800px) 650px, 1000px"     src="500x400.jpg"     alt="An example image">

这里使用到了  的 sizes 和 srcset 属性,主流浏览器都支持得很好,而在不兼容的浏览器里,会自动降级使用默认 的 src 属性,因此可以放心大胆地使用。

下面具体介绍这两个属性的用法。

srcset

一般形式:

srcset="[url] [num][descriptor], [url] [num][descriptor], …"

指定了一组可选的源,源之间用逗号分隔,每个源由两部分组成:

  1. 图片的 url

  2. 正整数+宽度描述符 w 或者 正浮点数+像素密度描述符 x,如果该项为空,则默认为 1x

浏览器会通过描述符来选择对应的源,如果使用密度描述符 x,则判断哪一项与设备像素比更接近,例如:

<img srcset="1200x800.jpg 2.5x,             800x600.jpg 2x,             600x400.jpg 1.5x"     src="500x400.jpg">

在 DPR = 2 的 iPhone 6 中会加载 800x600 的图片。

在 DPR = 3 的 iPhone X 中会加载 1200x800 的图片。

对于宽度描述符 w,由于需要与 sizes 属性一起使用,因此会在下面和 sizes 属性一起介绍。

sizes

一般形式:

sizes="[media-query] [size], [media-query] [size], …, [size]"

指定了一组可选的 size,size 之间用逗号分隔,每个 size 由两部分组成:

  1. 媒体查询,但是不能存在于最后一项,因为最后一项用作默认值

  2. 图片的 size(CSS 像素),可用 px、em、vw 等单位

当 srcset 属性使用 w 时,sizes 属性才会起作用,浏览器会根据下面的顺序加载图片。

  1. 浏览器逐项判断 sizes 属性中的媒体查询条件,当为真时取该项的 size 作为图片的大小信息,如果 的 CSS 样式没有指定大小,则会使用 size 作为  的大小

  2. 根据 size 和设备像素比,两者相乘得出图片的分辨率

  3. 从 srcset 的宽度描述符中选出不小于所得分辨率中最接近的一项,没有则选最大的一项,取该项作为图片的源

例如:

<img srcset="1200x800.jpg 1200w,             700x500.jpg 700w,             500x400.jpg 500w,             300x200.jpg 300w"     sizes="(max-width: 480px) 350px,             (max-width: 800px) 650px,             1000px"     src="500x400.jpg">

在 DPR = 1 和视口宽度 = 440px 的情况下,根据 sizes 属性获得 size 为 350px,计算 350x1 = 350,在 srcset 中不小于 350 又最接近的是 500w,所以会选择加载 500w 对应的 500x400 图片。

在 DPR = 2 和视口宽度 = 700px 的情况下,根据 sizes 属性获得 size 为 650px,计算 650x2 = 1300,在 srcset 中各项均小于 1300w ,所以会选择最大的 1200w 对应的 1200x800 图片。

以上就是 srcset 和 sizes 的用法,需要注意的是,以下情况是不正确的:

  • 在同一个 srcset 中混合使用了 x 和 w

  • 在同一个 srcset 有重复的描述符,比如有两项都是 2x

另外值得一提的是,当我们使用 srcset 属性时,实际上是向浏览器提供相关信息,让浏览器作出更好的选择,浏览器可能还会根据用户的偏好、网络条件等因素调整选择。而这个特点,就是接着要介绍的  与 +srcset 之间的重要区别之一。

如果对 srcset 和 sizes 还想了解更多,可以访问 MDN 的文档《响应式图片》(https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)。

艺术方向

艺术方向听上去可能比较让人费解,但如果用例子来解释就会非常简单。考虑如下情况:

我们提到将图片的 max-width 设置为 100%,图片就会在手机屏幕上压缩到视口的宽度,如果这张图片实际上很大,图片中的内容就会看不清,特别是如果图片主要内容集中在中间,如人像,浏览效果会比较差。遇到这样的情况,最好的方式是在不同的屏幕尺寸下采用不同的图片,让主要内容保持在视口中间,如下图。

(图片来源:https://developers.google.com/web/fundamentals/design-and-ux/responsive/images)

所以艺术方向可以理解为根据设备特征选用突出重点的不同图片,这些图片通常经过更改比例、裁剪等处理。

可以发现,与前面所说的分辨率切换不同,艺术方向对图片选择的要求更为严格。如果没有显示最合适的图片,对于分辨率切换,也只是看上去有点模糊或者消耗了更多流量,而对于艺术方向,就不能显示出主要内容,非常影响体验。

一般用  来实现艺术方向,的兼容性也很好,即使浏览器不兼容,也能回退到 

Picture

是一个图像和图像源的容器,包含多个 和一个 ,自身不会有任何的显示,只是提供了一个环境,让里面的  从中选择正确的源。

<picture>  <source media="(max-width: 500px)" srcset="cat-small.jpg">  <source media="(min-width: 1000px)" srcset="cat-big.webp" type="image/webp">  <img src="cat.jpg" alt="An cat img">picture>

浏览器从上到下检查 ,根据 media、type 和 srcset 属性进行匹配,发现符合就选择这个  的源作为  的源,如果都不符合,则不改变  的源。

的使用主要集中在 上, 具有三个属性:media、type 和 srcset,其中 srcset 和前面提到的类似,就不再介绍了,下面说说 media 和 type 两个属性。

media

类似于媒体查询,作为浏览器的判断条件,浏览器会严格按照 media 来选择 ,如果 media 不符合,浏览器会跳过该项,然后继续检查下一个 。

比如,要求视口宽度大于 800px 的情况:media="(min-width: 800px)"

type

指定了  图片源的 MIME type,如果浏览器不支持这个格式,则跳过该项,然后继续检查下一个 。

比如,指定图片是 WebP 格式:type="image/webp"

在上面例子中,如果是支持 WebP 格式且视口宽度 = 1200 的设备,浏览器首先检查第一个 ,由于 1200 大于 500,所以跳过这个 ,接着检查下一个 。由于设备支持 WebP 格式,1200 大于 1000,第二个  的条件都满足,浏览器就选择其作为  的源,因此会加载 cat-big.webp。

(图片来源:https://webapplog.com/programmer-vs-software-engineer-vs-software-developer-vs-coder/)

而在 iPhone 6 中,375 小于 500,第一个  满足条件,因此浏览器会加载 cat-small.jpg。

小结

以上就是响应式图片设计中关于分辨率切换艺术方向的实现方法,用到了  与 +srcset,这两者在使用上还有一些需要注意的地方:

  1. 中的元素要注意顺序,浏览器是按照顺序匹配的,因此顺序错误可能会导致选择了错误的图片。如果  不放在最后,那么其后面的  会失效,因为浏览器最多匹配到  就结束了。

  2. 由于两种方案都能代替原来的 src,因此不能通过 img.src 获取实际加载的图片地址,可以等图片加载完后通过 img.currentSrc获取真正的图片地址,例如:

    img.addEventListener('load', () => { console.log(img.currentSrc || img.src)})
  3. 避免使用  的sizes 属性,不要混用  与 ,这会让情况变得复杂而且代码难以维护,例如:

    <picture>  <source media="(max-width: 600px)"          sizes="500px"          srcset="600.jpg 600w, 1200.jpg 1200w">  <source media="(max-width: 1200px)"          sizes="1000px"          srcset="1200.jpg 1200w, 2300.jpg 2300w">  <img src="800.jpg" srcset="600.jpg 1x, 1200.j" alt="my image">picture>

可能你会觉得 与 +srcset 在功能上差不多,都是根据设备条件选择不同的源,但两者存在一些差别:

  1. +srcset 是提供信息给浏览器,让越来越智能的浏览器作出决定,更轻量和简单

  2. 可以让你声明式地为浏览器提供不同的源,浏览器会严格按照 media 和 type 属性去匹配 ,所以需要开发者更细心地设计断点等条件。而且通过 type 属性,可以使用没有完全兼容的新格式图片,如具有更高压缩率的 WebP ,在支持 WebP 的浏览器中,可以节省更多流量,提高加载速度。

因此建议在分辨率切换这种更为简单的情况下,尽量使用 +srcset 这一方案,而在艺术方向这种对显示要求更严格的情况下,应该选择使用 。

图片的其他注意事项

响应式图片是响应式布局中的重要部分,需要考虑是否会带来性能问题。在开发过程中,还需要注意以下几个方面:

  1. 对图片进行懒加载

  2. 对于小的简单的图片,可以使用矢量图或者字体,保证在不同尺寸设备下都很清晰

  3. 对于尺寸小的图片,可以使用 Data URI 的方式,将图片转成 base64 内联在 CSS 或者 HTML 中,避免请求,但这样同样无法利用 HTTP 缓存,因此一般只对小于 1.5K 的图片做处理

  4. 挑选恰当的图片格式,PNG,JPEG 等,可以在 Android 下使用 WebP 格式

  5. 对图片进行压缩和优化

  6. 采用 CSS 和 CSS 动画代替一些简单的图片和动态图,如加载中 GIF 图

总结

本文从图片在不同设备中的显示问题出发,分析了为什么需要进行图片的响应式设计,然后进一步说明响应式图片的两大应用场景:分辨率切换和艺术方向。根据这两个方向的特点,通过代码和例子介绍了响应式图片的主要实现方法: 和 +srcset,并比较了这两种方法的区别,最后提出了一些使用上的建议以及响应式图片开发中的注意事项。

以上内容在实际开发中不一定完全适用,开发者应根据具体情况作出更合适的选择,比如断点、图片大小采用的单位等,而且响应式图片还需与响应式文字、响应式布局等方面进行配合,才能实现更好的响应式效果,改善用户的体验。

本文内容主要来自开源书籍《PWA 应用实战》。该书由百度 Web 生态团队撰写与分享,记录了团队过去两年积累的 PWA 方面的经验,欢迎对 Web 和 PWA 有浓厚兴趣的读者加入我们,一起来维护这本书。

Brilliant Open Web 

BOW(Brilliant Open Web)团队,是一个专门的Web技术建设小组,致力于推动 Open Web 技术的发展,让Web重新成为开发者的首选。

BOW 关注前端,关注Web;剖析技术、分享实践;谈谈学习,也聊聊管理。

关注 OpenWeb开发者,让我们一起推动 OpenWeb技术的发展!

OpenWeb开发者

ID:BrilliantOpenWeb

技术连接世界,开放赢得未来

判断两个图片的特征向量_响应式布局提高篇 图片正确的打开方式相关推荐

  1. html响应式布局平移,jQuery图片内部缩放和平移插件jquery.zoom.js

    插件描述:jquery.zoom.js是一款非常实用的图片内部缩放和平移jQuery插件.该插件可以鼠标滑过图片,点击图片或移动手机上触摸图片时,将图片进行放大或平移操作. 简要教程 jquery.z ...

  2. ios解锁动态图片_升级iOS10后的解锁界面 正确的打开方式是这样!(图)

    刚升级到iOS 10的小伙伴最直观的感受可能就是锁屏界面的改变了.从前只要按下电源键点亮屏幕,手指轻触Home键(不需要按下)就能轻松解锁手机.而现在点亮之后则必须按下Home键才行(广大非iPhon ...

  3. html响应式布局ipad,响应式布局(Responsive design)

    意在实现不同屏幕分辨率的终端上浏览网页的不同展示方式.通过响应式设计能使网站在手机和平板电脑上有更好的浏览阅读体验. 步骤 1.布局及设置meta标签 当创建一个响应式网站,或者非响应式网站变成响应式 ...

  4. HTML+CSS_第三部分(Flex弹性盒子布局、grid网格布局、移动端、移动端流式布局、移动端rem布局、响应式布局、Bootstrap框架)

    文章目录 (1)Flex弹性盒子布局 一: 父容器上的属性 1. display:flex 设置为弹性盒子(写在父容器上) 2.flex-direction值 设置子项的布局方向(写在父容器上) 3. ...

  5. 流体式布局与响应式布局_将固定像素设计转换为流体比例布局

    流体式布局与响应式布局 Responsive web design has been a prime necessity for every enterprise ever since Google ...

  6. 计算机视觉 响应_视觉响应式布局的自动化测试

    计算机视觉 响应 Today it's all about testing. In 2015, many developers knows about TDD and I personally thi ...

  7. 响应式网页设计_响应式网页设计中的常用技术

    响应式网页设计 在先前的文章中,我讨论了为什么Web准备就绪以进行响应式设计 ,以及网站所有者如何使用用户设备和屏幕空间的上下文来跨各种尺寸的屏幕(包括PC,电话) 为用户提供上下文相关的体验.和控制 ...

  8. 响应式布局必懂知识_五分钟教会你响应式布局

    第一:正确理解响应式布局 第二:响应式设计基本步骤 第三:响应式设计注意事项 第四:响应式布局实现原理 第一:正确理解响应式布局 响应式网页设计就是一个网站能够兼容多个终端,而不是为每个终端都做一个特 ...

  9. 移动端web页面响应式布局(文字、图片、表格)

    移动端web页面响应式布局 絮絮叨叨: 最近被领导抓去写了个前端页面,还要是适应移动端的..还三天要完成..前端小白 的我硬生生刚出来了,这两天正好闲了点,总结总结. 设置meta 写过前端的小伙伴们 ...

最新文章

  1. Docker实践(6)—CentOS7上部署Kubernetes
  2. 我们能达到电影里的智能吗?最可能实现的AI场景是什么?如何看待AI自主性?...
  3. 富士通打印机调整位置_打印机为什么卡纸 打印机四种卡纸原因及解决办法【介绍】...
  4. Spark Stream整合flum和kafka,数据存储在HBASE上,分析后存入数据库
  5. 关于mysql的error-based injection payload
  6. Nacos与Eureka的区别有哪些?
  7. layout_gravity 和 gravity
  8. mysql 不能添加外键 1215_MySQL错误1215:无法添加外键约束
  9. 计算机英语讲课笔记05
  10. LightOJ - 1282 Leading and Trailing
  11. matlab常用函数通俗解释(fft2和fftshift函数设置问题等)
  12. abaqus6.14安装教程 如何设置中文
  13. 基于springboot助学贷款管理毕业设计源码061528
  14. PS中如何简单、快速更换照片的背景色
  15. mysql上线脚本规范_专业规范的mysql启停脚本
  16. excel分列---多页批量操作--vba宏实现
  17. Life Restart 人生模拟器 网址
  18. python生成递归json_python函数、递归、json模块操作
  19. 光端机、光纤收发器与光猫三者之间的区别介绍
  20. Android 常用开源库总结-2020年

热门文章

  1. 超详细配置教程,搭建 Windows 深度学习环境
  2. 结构最清晰的Yolov3 head和loss实现完全解析
  3. EMNLP2020:Hugging Face获最佳demo
  4. 神经网络“天生”就会驾驶虚拟赛车
  5. Django项目配合sentry实现浅析
  6. Jupyter notebook 指定 Python 解释器 anaconda
  7. 计算机网络-编码与调制
  8. 一个雷达和摄像头融合的3D目标检测方法CenterFusion
  9. 自动驾驶的视觉感知包括哪些内容?
  10. 基于OpenCV的实用图像处理操作