前言

之前写过 HTML & CSS – Responsive Image 响应式图片 (完整版), 里面解释了原理和一些具体做法, 但是并不是以真实场景作为例子带入.

由于 RWD Image 挺复杂, 所以特地再写一篇以实战的角度来解释.

建议先阅读之前的相关文章:

CSS – RWD (Responsive Web Design) 概念篇

CSS – 屏幕, 打印, 分辨率, 物理像素, 逻辑像素, Retina, DPI, PPI 是什么?

HTML & CSS – Responsive Image 响应式图片 (完整版)

屏幕 Resolution Research

RWD 的要求是在不同的屏幕尺寸下自适应设计. 那么第一步就是要先搞清楚, 到底屏幕尺寸有哪些.

市场虽然已经有了 standard 的 Breakpoint (Bootstrap 和 Tailwind CSS 各一个版本), 但是这种全世界通用的尺寸, 不一定适合所有项目.

更何况这个 Breakpoint 是 for RWD Design 而不是 RWD Image.

如果网站已经有访问数据, 那么可以直接从 Google Analytics 里面查看, 用户使用的设备尺寸. 如果网站还没有数据, 那么可以通过 statcounter 查看

电脑屏幕 resolution:

新加坡:

马来西亚:

1920 x 1080 是 desktop 用的屏幕. DPR (device pixel ratio) = 1

1280 x 720   是 laptop 1920 x 1080 的屏幕但是 display resolution 调成了 150%. 所以它的 DPR = 1.5 (1280 是逻辑像素, 1920 是物理像素)

1536 x 864   是 laptop 1920 x 1080 的屏幕但是 display resolution 调成了 125%. 所以它的 DPR = 1.25 (1536 是逻辑像素, 1920 是物理像素)

1366 x 768   是 laptop 1366 x 768 的屏幕, 这个是廉价屏幕, 所以它物理像素本来就很少 (不是高清)

1440 x 900   是 MacBook 苹果电脑 2880 x 1800 的屏幕但是 display resolution 调成了 200%. 所以它的 DPR = 2 (1440 是逻辑像素, 2880 是物理像素)

2560 x 1440 我不清楚, 1600 x 900 是廉价的 desktop 屏幕 (这 2 个太少了, 我就不打算支持了)

手机屏幕 resolution:

新加坡:

马拉西亚

414 x 896 是 iPhone (XR, XS Max, 11, 11 Pro Max), DPR = 2 和 3 都有 (看机型)

390 x 844 是 iPhone (12, 12 Pro), DPR = 3

375 x 812 是 iPhone (X, 11 Pro), DPR = 3

428 x 926 是 iPhone 12 Pro Max, DPR = 3

360 x 800 是 LG, Samsung, Hua Wei, DPR = 2, 3 ,4

360 x 780 是 iPhone 12 mini 和各种 Android 机, DPR = 2, 3, 4

393 x 873 是 Xiaomi, DRP = 2.75

平板屏幕 resolution:

我只关注 iPad

768 x 1024 是 iPad 6th gen portrait, DPR = 2

810 x 1080 是 iPad 7th gen portrait (到目前的 9th 都是), DPR = 2

1024 x 768 是 iPad 6th gen landscape, DPR = 2

1080 x 810 是 iPad 7th gen landscape (到目前的 9th 都是), DPR = 2

尺寸资料来源

尺寸资料是从这里这里这里获取的.

Intrinsic Size & Rendered Size

图片有两个尺寸, 一个是 Intrinsic size (固有尺寸), 另一个是 Rendered size (显示尺寸).

使用 Chrome dev tool 就可以看见了

Intrinsic size 指的是这张图的 physical dimensions pixel (物理像素). 它不会受 CSS style 影响

Rendered size 指的是这张图最终显示出来的 dimension pixel (逻辑像素). 它会受 CSS style 影响

例子说明:

<img src="https://via.placeholder.com/3200x1800" />

一张 3200 x 1800 的图放到 img 里, width heght 默认是 auto

这时 intrinsic 和 rendered size 都是一样的, 3200 x 1800, 因为 width height auto 的意思是显示完整的图片.

但如果加上 CSS width: 300px

intrinsic size 依然是 3200 x 1800 (它不受 CSS 影响), 但是 rendered size 就变成了 300 x 168.75.

因为 CSS 声明了 width 是 300px 而 height auto 则表示图片按照原始比例缩小, height 就变成了 168.75

按比例缩小的算法是 new height = new width * old height / old width (我的背法是 新的 乘于对角 然后 除)

The Problem

intrinsic 大于 rendered 就表示浪费了带宽. (SEO performance 会扣分)

intrinsic 小于 rendered 就表示图片太小, 图片会变蒙 (失真)

除了上面这种同比例缩小的情况, 不同比例也会导致 intrinsic != rendered size

举例:

原图 320 x 180

CSS width: 160px; height: 180px; object-fit: cover;

最终图片只显示了 horizontal 中间的部分.

rendered size: 160 x 180 (160px 的 width 浪费了)

The Solution

RWD Image 要解决的问题就是这些. 它的思路很简单, 就是通过 media query 去判断当前屏幕.

然后换一张合适的图片, 尽可能让图片 intrinsic 和 rendered 一致, 既不失真也不浪费带宽

有几个维护成本需要被考虑:

1. 这个方案是拿空间换时间, 准备多张不同尺寸的图片并不容易. 而且浪费 disk space.

2. RWD Image 是不依赖 CSS 渲染的, 也就是说, 虽然 rendered size 是 CSS 搞出来的. 但是当我们在做 RWD Image 时却无法依赖 CSS

需要直接给出最终的数字. CSS 可以写 100%, 但 RWD 不能写 100%, 它只能依据不同尺寸的屏幕 hardcode 写 rendered 多少 px.

这是因为 browser 在处理 img srcset 或者 picture source srcset 时是没有去解析或依赖 CSS style 的.

3. Google Lighthouse 会有一些评分标准, intrinsic 和 redered size 差太远就会报 error 了, 比如差了 4 KiB

简单案例 img + srcset + size

HTML

<header>Header</header>
<main>
<img src="https://via.placeholder.com/3200x1800" />
<img src="https://via.placeholder.com/3200x1800" />
</main>

CSS Style

header {
font-size: 2rem;
padding-block: 1rem;
text-align: center;
background-color: crimson;
color: white;
}
main {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
img {
max-width: 100%;
}
}

header 只是为了美而已.

效果

中间的 2 张图, 在不同的屏幕尺寸下, 它们的 dimension 都不一样.

每一个 rendered size 和 intrinsic size 也都不一致.

图片准备

我挑出几个 size 来准备 for example 就好.

Android (360w, DPR: 2, 3, 4)

rendered size 最好的获取方式是用 dev tool 去查看 (如果 CSS 很简单的话, 也可以自己算)

rendered size = 360 x 202.5

2x = 720 x 406 (注: 这里微差的算法因人而异, 我的做法是 202.5 ceil to 203 then x2 = 406)

3x = 1080 x 609 (注: 203 x 3 = 609)

4x = 1440 x 812

iPhone (414w, DRP: 2, 3)

rendered size = 414 x 232.88

2x = 828 x 466

3x = 1242 x 699

iPad (810w, DPR: 2)

rendered size = 397 x 223.31

2x = 794 x 448

图片的比例都是 16:9. 一共 6 张图 width: 720, 1080, 1440, 828, 1242, 794.

srcset + size

所有图片的比例都是一样的 16:9 只是 dimension 不同, 这个属于 Resolution switching: Different sizes and different resolutions, 不是 Art direction 所以不需要用 picture element 也可以解决.

<img
srcset="
https://via.placeholder.com/720x406 720w,
https://via.placeholder.com/1080x609 1080w,
https://via.placeholder.com/1440x812 1440w,
https://via.placeholder.com/828x466 828w,
https://via.placeholder.com/1242x699 1242w,
https://via.placeholder.com/794x448 794w,
https://via.placeholder.com/3200x1800 3200w
"
sizes="(max-width: 360px) 360px, (max-width: 414px) 414px, (max-width: 810px) 397px, 3200px"
src="https://via.placeholder.com/3200x1800"
width="3200"
height="1800"
/>

srcset 把所有图片列出来. 720w 是 phisical pixel.

sizes 的匹配顺序是 if else 哦, 第一个进到了就不会往下走了, 所以合理的匹配方式是使用 max-width 也就是 <= 360px, <=414px, <=810px

(max-width: 810px) 397px 的意思是当 viewport <= 810px 的时候, 图片的 rendered size 是 397px.

810 是 iPad 所以它的 RDP 是 2, rendered size 397px x 2 = 794px. 所以最终会去 srcset 里面找 794px 的图作为显示.

width dynamic 写法

上面这种写法是完全 hardcode 的, 当 media 是多少, image rendered size 是多少 px

其实也可以写成 dynamic 的 比如

<img
sizes="(max-width: 414px) 100vw, (max-width: 810px) calc((100vw - 1rem) / 2), 3200px"
/>

这个和上面是完全等价的效果.

当 viewport 414px 时, width 时 100vw

当 viewport 810px 时, width = vw 扣掉中间的 gutter (1rem) 然后 50% 就是 image rendered size

注意 : 不能写 % 哦, calc 可以但 min(), max() 函数是不支持的哦

一个比较好的管理方式是, follow RWD 的 Breakpoint 然后里面写 dynamic 算法 depend on vw. 然后准备几张图. 大概一个间隔就可以了.

虽然这做法无法到达 100% rendered size 和 intrinsic 一致, 但是 trade-off 到很合理. 维护也比较容易.

具体做法是这样的, 把所有 rendered size 列出来, 然后每间隔 100px 就保留一张图, 然后 media <= 639 就 100vw.

复杂案例 picture > source

HTML & CSS – 实战 RWD Image 响应式图片的更多相关文章

  1. 【读书笔记《Bootstrap 实战》】3.优化站点资源、完成响应式图片、让传送带支持手势

    A.优化站点资源 速度很重要.用户很关心.我们的站点必须加载够快,否则用户就会走人.SEO 也很重要.我们的站点必须加载够快,否者搜索排名就会下降. 明白了这样,我们就来清点一下 [Bootstrap ...

  2. CSS 与 HTML5 响应式图片

    什么是响应式图片? 响应式图片是指:用户代理根据输出设备的分辨率不同加载不同类型的图片,不会造成带宽的浪费.同时,在改变输出设备类型或分辨率时,能及时加载对应类型的图片. CSS3 响应式图片 对于很 ...

  3. CSS与HTML5响应式图片

    随着 Retina 屏幕的逐渐普及,网页中对图片的适配要求也越来越高.如何让图片在放大了两倍的 Retina 屏幕显示依然清晰,曾经一度困扰着网页开发者,好在 CSS3 与 HTML5 已经着力在改变 ...

  4. 【Bootstrap】3.优化站点资源、完成响应式图片、让传送带支持手势

    A.优化站点资源 速度很重要.用户很关心.我们的站点必须加载够快,否则用户就会走人.SEO 也很重要.我们的站点必须加载够快,否者搜索排名就会下降. 明白了这样,我们就来清点一下 [Bootstrap ...

  5. web响应式图片设计实现

    .header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...

  6. 继续送假期干货——响应式图片工具smartImg

    中午看<众妙之门>看到一个响应式图片处理工具(点此查看)的介绍,然后就心血来潮想着不妨自己写一个基于JQ的吧,于是就又有了这么一个干货给大家. smartImg 的全部文件可以从我的Git ...

  7. bootstrap-内联表单 水平(横向)表单 响应式图片 辅助类 [转]

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. 如何使用 HTML5 的picture元素处理响应式图片

    来自: http://www.w3cplus.com/html5/quick-tip-how-to-use-html5-picture-for-responsive-images.html 图片在响应 ...

  9. bootstrap中如何让响应式图片(img-responsive)水平居中

    我们在用bootstrap排版内容的时候,有的时候在内容中需要图片水平居中对齐. 一般情况下,我们的图片都使用了 .img-responsive 类来实现响应式图片.如果需要实现响应式图片水平居中,那 ...

  10. 响应式图片srcset学习

    响应式图片srcset全新释义sizes属性w描述符 先转再看

随机推荐

  1. 手写数字识别-使用TensorFlow构建和训练一个简单的神经网络

    下面是一个具体的Python代码示例,展示如何使用TensorFlow实现一个简单的神经网络来解决手写数字识别问题(使用MNIST数据集).以下是一个完整的Python代码示例,展示如何使用Tenso ...

  2. Oracle 死锁与慢查询总结

    查看死锁 SELECT s.sid "会话ID", s.lockwait "等待锁", s.event "等待的资源/事件", -- 最近等 ...

  3. 解密prompt系列34. RLHF之训练另辟蹊径:循序渐进 & 青出于蓝

    前几章我们讨论了RLHF的样本构建优化和训练策略优化,这一章我们讨论两种不同的RL训练方案,分别是基于过程训练,和使用弱Teacher来监督强Student 循序渐进:PRM & ORM So ...

  4. Linux 破解mysql密码

    mysql忘记密码怎么办 [root@master ~]# mysql -uroot -pHuawei123123$ mysql: [Warning] Using a password on the ...

  5. 备份服务器eBackup

    目录 软件包方式安装eBackup备份软件   1.前景提要   2.创建虚拟机   3.安装备份软件.   4.安装 eBackup 补丁   5.配置 eBackup 服务器   6.访问web界 ...

  6. 【Vue】Vue-Cli 安装

    首先需要Node.js环境支持: Node.js官网下载: https://nodejs.org/en/ 右边稳定版,左边最新版 下载安装程序之后双击运行,无脑下一步 打开终端输入版本查看命令: no ...

  7. 日本联合研究团队发布 Fugaku-LLM——证明大型纯 CPU 超算也可用于大模型训练

    相关: https://mbd.baidu.com/newspage/data/landingsuper?context={"nid"%3A"news_101396655 ...

  8. mujoco安装报错:mujoco_py/cymj.pyx:67:5: Exception check on 'c_warning_callback' will always require the GIL to be acquired.

    参考: https://blog.csdn.net/weixin_49373427/article/details/131981583 https://blog.csdn.net/CCCDeric/a ...

  9. FAT32和NTFS文件系统的区别

    文件系统对于在计算设备上运行至关重要. 因此,选择正确的文件系统变得很重要. FAT32 和 NTFS 是两个具有显着差异的文件系统. 1.磁盘分区容量区别 NTFS可以支持的分区(如果采用动态磁盘则 ...

  10. java中的几种锁

    一.公平锁/非公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁.有可能,会造成优先级反转或者饥饿 ...