0 tl;dr
其实也没啥原理,就是一个比例问题。
1 前置知识
设备独立像素(DIP):一种抽象的像素,与实际物理像素之间的比值就是DPR。简而言之,一个设备独立像素实际上可以由\(1\times1\),\(2\times2\),\(3\times3\)...等任意多个物理像素来表现,取决于设备的设置。而应用一般并不需要实际与物理设备打交道,只与设备独立像素打交道。
理想视口:布局视口等于设备独立像素宽度的视口,可以简单理解为设置了viewport meta标签的html页面。
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
接下来讨论的适配问题都是关于理想视口下设备独立像素的。
2 淘宝适配方案
定义几个变量:设计稿宽度x, 设计稿中任意边长a, 最终设备独立像素宽度 d, a实际渲染的长度a'
最终要在设备中渲染出a',也就是要找出a -> a'的等式。
不难得出一个等式
对该式移项,可得
这里就可以将\(a\)作为转换后的长度;而\(\frac{d}{x}\)作为单位,动态添加。这里html的rem刚好是这样的单位,所以可以将\(\frac{d}{x}\)设置为html的font-size值,而长度数值不变,单位设置为rem。最终css计算的时候乘以这个font-size值就OK。
然而\(\frac{d}{x}\)往往都不会很大(就算是d=1920,在x=375的时候也只有5.12),又由于font-size属性不支持小于12px的值,所以乘以了100以避免被强制提升到12px,另外也方便计算。换句话说,前面对应地要除以100。等式改写为
根据这个式子,可以很快拆出需要的部分:
根据这个思路可以给出一个实际的例子:MDN 的 EM 示例
利用浏览器body默认font-size为16px,设置font-size为62.5%,页面各处样式都可以使用1rem = 10px的等式。
3 唯品会方案
还是同样的前设:
设计稿宽度x, 设计稿中任意边长a, 最终设备独立像素宽度 d, a实际渲染的长度a'
这里唯品会的做法是:引入一个完全固定的中间量10,则上式改为
拆分之后的结果是
4 总结
使用淘宝方案可以拓展到任意尺寸的设计稿,用法都是一致的;唯品会方案在借助工具(lib-flexible)的情况下才易用,但思路上来说更贴近于使用vw单位。
至于lib-flexible是手机淘宝系的开源产品,那就是另外一个故事了🥱