HTML & CSS – 实战 RWD Image 响应式图片
前言
之前写过 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 响应式图片的更多相关文章
- 【读书笔记《Bootstrap 实战》】3.优化站点资源、完成响应式图片、让传送带支持手势
A.优化站点资源 速度很重要.用户很关心.我们的站点必须加载够快,否则用户就会走人.SEO 也很重要.我们的站点必须加载够快,否者搜索排名就会下降. 明白了这样,我们就来清点一下 [Bootstrap ...
- CSS 与 HTML5 响应式图片
什么是响应式图片? 响应式图片是指:用户代理根据输出设备的分辨率不同加载不同类型的图片,不会造成带宽的浪费.同时,在改变输出设备类型或分辨率时,能及时加载对应类型的图片. CSS3 响应式图片 对于很 ...
- CSS与HTML5响应式图片
随着 Retina 屏幕的逐渐普及,网页中对图片的适配要求也越来越高.如何让图片在放大了两倍的 Retina 屏幕显示依然清晰,曾经一度困扰着网页开发者,好在 CSS3 与 HTML5 已经着力在改变 ...
- 【Bootstrap】3.优化站点资源、完成响应式图片、让传送带支持手势
A.优化站点资源 速度很重要.用户很关心.我们的站点必须加载够快,否则用户就会走人.SEO 也很重要.我们的站点必须加载够快,否者搜索排名就会下降. 明白了这样,我们就来清点一下 [Bootstrap ...
- web响应式图片设计实现
.header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...
- 继续送假期干货——响应式图片工具smartImg
中午看<众妙之门>看到一个响应式图片处理工具(点此查看)的介绍,然后就心血来潮想着不妨自己写一个基于JQ的吧,于是就又有了这么一个干货给大家. smartImg 的全部文件可以从我的Git ...
- bootstrap-内联表单 水平(横向)表单 响应式图片 辅助类 [转]
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 如何使用 HTML5 的picture元素处理响应式图片
来自: http://www.w3cplus.com/html5/quick-tip-how-to-use-html5-picture-for-responsive-images.html 图片在响应 ...
- bootstrap中如何让响应式图片(img-responsive)水平居中
我们在用bootstrap排版内容的时候,有的时候在内容中需要图片水平居中对齐. 一般情况下,我们的图片都使用了 .img-responsive 类来实现响应式图片.如果需要实现响应式图片水平居中,那 ...
- 响应式图片srcset学习
响应式图片srcset全新释义sizes属性w描述符 先转再看
随机推荐
- 3.5 Y84-64的流水线实现
我们终于准备好要开始本章的主要任务--设计一个流水线化的Y86-64处理器.首先,对顺序的SEQ处理器做一点小的改动,将PC的计算挪到取指阶段.然后,在各个阶段之间加上流水线寄存器.到这个时候,我们的 ...
- SparkSQL on K8s 在网易传媒的落地实践
作者:鲁成祥 易顺 随着云原生技术的发展和成熟,大数据基础设施积极拥抱云原生是业内发展的一大趋势.网易传媒在 2021 年成功将 SparkSQL 部署到了 K8s 集群,并实现与部分在线业务的混合部 ...
- Python 按分类权重(区间)随机获取分类样本
按分类权重(区间)随机获取分类样本 By:授客 QQ:1033553122 开发环境 win 10 python 3.6.5 需求 活动抽奖,参与抽奖产品有iphone, 华为,小米,魅族,vivo, ...
- Vue 给mapState中定义的属性赋值报错的解决方案
Vue 给mapState中定义的属性赋值报错的解决方案 by:授客 QQ:1033553122 1. 实践环境 Vue 2.9.6 2. 问题描述 <script> import ...
- 关于SpringBoot中事务回滚没有生效
在SpringBoot中,事务回滚可以用注解@Transactional标识. Spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作. 1.非检查型异常 ...
- RHCA cl210 016 流表 overlay
Overlay网络是建立在Underlay网络上的逻辑网络 underlay br-int 之间建立隧道 数据流量还是从eth1出去 只有vlan20 是geneve隧道.只有租户网络有子网,子网需要 ...
- 【Vue】Re19 Promise
一.概述 Promise是异步编程的解决方案 异步事件的处理: 封装的异步请求函数不能立即获取结果, 通常会传入另外一个函数,在请求成功的时候将数据通过传入的函数回调出去 如果只是一个简单的请求,那么 ...
- 【Mybatis-Plus】01 快速上手
[官网快速上手地址] https://mp.baomidou.com/guide/quick-start.html#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A5%E7%A8 ...
- 国产操作系统 deepin —— UOS 系统下使用蓝牙音箱或蓝牙耳机不能正常工作
近日搞来了一个国产CPU的电脑,自带系统为UOS,具体可见: https://www.cnblogs.com/devilmaycry812839668/p/14828130.html 忽然发现这个系统 ...
- 在Ubuntu18.04系统中源码安装 gcc7.3.0
本文给出源码安装gcc7.3.0的方法. 依赖的环境安装到自建文件夹下, 给出下面操作中环境的安装文件夹: /home/devilmaycry/anaconda3/mindspore_envs这个路径 ...