把我的个人网站推倒重来(Part 4 - Responsive Image)

栏目: CSS · 发布时间: 7年前

内容简介:网站整体完成后,我就可以开始做各种小优化了。其中一个优化是使用 responsive image 来适应不同分辨率和不同像素密度的屏幕,用到的是<img />新增的srcset和sizes属性以及新增的<picture />元素。因为现在有多套新旧并存的 responsive image 方案,而且它们使用的属性存在重叠,所以要搞清楚到底这些属性如何运作,还是要动手实验。这是一段这一切看起来都很简单,但这是因为我们只在讨论分辨率没在讨论像素密度。如果是 2 倍像素密度的 Retina Display,上述

网站整体完成后,我就可以开始做各种小优化了。其中一个优化是使用 responsive image 来适应不同分辨率和不同像素密度的屏幕,用到的是<img />新增的srcset和sizes属性以及新增的<picture />元素。因为现在有多套新旧并存的 responsive image 方案,而且它们使用的属性存在重叠,所以要搞清楚到底这些属性如何运作,还是要动手实验。

sizes属性

<img srcset="elva-fairy-320w.jpg 320w,             elva-fairy-480w.jpg 480w,             elva-fairy-800w.jpg 800w"     sizes="(max-width: 320px) 280px,            (max-width: 480px) 440px,            800px"     src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

这是一段 来自 MDN 的代码 。虽然大家都是先写srcset再写sizes,但其实更符合直觉的阅读顺序是先读sizes。sizes的值是一组类似 media query 的命令,它们描述了在什么情况下这个<img />应该有多宽。拿上面这段代码举例:如果屏幕宽度是 320px 或以下,图片宽度为 280px;如果屏幕宽度是 480px 或以下(但 320px 以上),图片宽度为 440px;其它屏幕宽度,图片宽度默认为 800px。

这一切看起来都很简单,但这是因为我们只在讨论分辨率没在讨论像素密度。如果是 2 倍像素密度的 Retina Display,上述图片宽度计算是否保持不变?答案是跟 media query 一样保持不变。无论像素密度是多少,sizes关注的都是 CSS 像素而不是物理像素。我觉得这个设计是合理的,因为在描述<img />宽度时,我们的思维模式跟在写 CSS 时一样,所以应该使用 CSS 像素。

尽管在 MDN 的例子中sizes属性的取值都是固定值,但其实这里可以使用calc()表达式进行复杂的计算,如我的代码中就用到了 calc(100vw - 30px) ,意思是100%的 viewport 宽度减去屏幕两侧各15px的margin。

srcset属性

看完sizes接着看srcset。在上面这段代码里,我们看到了一个神奇的单位叫做w,这是指代图片文件的像素宽度。文件图片的像素宽度跟<img />的 CSS 像素宽度不是 1:1 对应的吗?这需要看像素密度。如果<img />的宽度是100px,像素密度是 1 时最佳图片文件宽度是100w;像素密度是 2 时最佳图片文件宽度是200w;像素密度是 3 时最佳文件宽度是300w;如此类推。

在上面这段代码中,srcset描述了 3 个图片文件地址,它们的文件图片像素宽度分别是320w、480w、800w。这也就是说,如果在一个 1000px 宽 1 像素密度的屏幕上,根据sizes这个<img />的宽度应该是800px,因此应该选择800w的图片文件地址;如果在一个 480px 宽 2 像素密度的屏幕上,根据sizes这个<img />的宽度应该是440px,但因为像素密度为 2 所以最佳图片文件宽度是880w,由于找不到880w的图片文件地址所以选用略差一档的800w图片文件地址。

为什么sizes和srcset这两个属性要如此设计呢?因为在之前的标准(如 CSS media query)里,我们需要在代码中描述如何根据两个变量(屏幕宽度和像素密度)来选择正确的图片文件地址,这个过程超级复杂,看 这篇文章 就能理解为什么这样的标准不好用。为了解决这个问题,新的标准让我们把这两件事情分离开来:sizes决定图片在 CSS 布局中的大小,但跟像素密度无关;srcset提供文件图片像素宽度,浏览器会自行根据sizes的结果和像素密度作出最佳选择,我们根本不需要知道像素密度。

(如果<img />在布局中的大小永恒不变,可以不设置sizes属性,然后在srcset中使用x单位描述像素密度而不使用w单位。这时候2x、3x可以对应不同的图片文件地址,浏览器会作出正确的选择。之所以我不选择这样做,是因为我的<img />大小本身需要 responsive,所以必须用sizes。因为w和x这两种单位不能在同一个<img />上混合使用,所以我用了w。)

src属性

看完sizes和srcset这两个属性后,最后我们看src属性。这是给那些看不懂前两个属性的老浏览器看的,也就是默认的图片文件地址。

<picture />元素

上述<img />元素属性能够实现同一张图片适应不同的屏幕尺寸和像素密度,但做不到根据屏幕尺寸现实不同的图片。我的网站首页布局本身是 responsive 的:如果屏幕宽度至少有 768px,使用左右两栏布局;否则使用一栏布局。

把我的个人网站推倒重来(Part 4 - Responsive Image)

左侧栏只显示我的个人照片,所以在能够使用两栏布局时我希望显示正方形(1:1)的剪裁。同样的剪裁显示在只能显示一栏的手机屏幕上就会显得很占地方,因此我需要换个剪裁方式(3:2)减少它占用的垂直高度,把更多的首屏垂直高度留给文本信息。

把我的个人网站推倒重来(Part 4 - Responsive Image)

为了实现根据屏幕尺寸使用不同的剪裁,我必须引入<picture />元素然后在里面放入<source />和<img />。

<picture>  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">  <source media="(min-width: 800px)" srcset="elva-800w.jpg">  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"></picture>

这也是一段 来自 MDN 的代码 。浏览器在碰到<picture />后,就开始按顺序看里面的<source />。每个<source />元素都有media属性,浏览器就如同执行 media query 一样来判断这个media属性的值是否通过,通过了就使用这个<source />来显示图片,后面的子元素都会被忽略掉。如果所有<source />都无法通过 media query 检测,最后那个<img />就会用来显示。(不兼容<picture />和<source />的老浏览器只会显示<img />。)

由于<source />支持上述<img />特有的sizes和srcset属性,所以就算是放在<source />中的图片也可以用上述方式支持不同的像素密度。考虑到大多数移动浏览器都会获得及时更新,能够支持<picture />和<source />,所以我选择了把正方形的剪裁当作默认剪裁放在 <img /> 里面,而针对小屏幕的剪裁放在 <source /> 里面。老旧的桌面浏览器如果打开我的网站首页,就算什么新元素和属性都不认识,至少能够根据img.src显示默认图片(像素密度为 1 的正方形剪裁)。

总结一下,如果需要针对不同的屏幕尺寸显示不同的图片(尤其是剪裁不一样的),必须使用<picture />配合<source />来选择正确的图片。一旦选定图片后,根据屏幕尺寸和像素密度设定图片尺寸只需要用到sizes和srcset属性。

我的图片优化不仅仅用到了首页的个人照片上,也用到了项目页面的截图上。在图片之后,我们还有很多其它东西可以优化的,欢迎通过 邮件RSS/Atom 订阅我的博客,继续关注后继文章。


以上所述就是小编给大家介绍的《把我的个人网站推倒重来(Part 4 - Responsive Image)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Domain-Driven Design Distilled

Domain-Driven Design Distilled

Vaughn Vernon / Addison-Wesley Professional / 2016-6-2 / USD 36.99

Domain-Driven Design (DDD) software modeling delivers powerful results in practice, not just in theory, which is why developers worldwide are rapidly moving to adopt it. Now, for the first time, there......一起来看看 《Domain-Driven Design Distilled》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具