1px 有多大?
我们先了解几个概念:
关键概念
设备像素: 设备屏幕实际拥有的像素点一般来说: 宽度方向有 1920 个像素点, 长度方向有 1080 个像素点.
逻辑像素: CSS 的像素单位(就是我们这次要讨论的 CSS 的 px), 其尺寸大小是相对的, 也称为独立像素
分辨率: 屏长的设备像素 * 屏宽的设备像素(1920 * 1080)
ppi(pixels per inch): 像素密度, 表示沿对角线每英寸长度的像素数目(单位是 dpi), 越大显示的越细腻
缩放因子(Scale Factor): 逻辑像素相对于设备像素的放大比例, 可通过 ` window.devicePixelRatio ` 获得, pc 上可以用个个性化来设置, 但二者并不完全等同
上面概念直接的关系
关系一:
设备尺寸 * 像素密度 = 分辨率(设备像素)
举例:
iphone6s 对角线长度为 5.5 inches, 像素密度 401 ppi, 分辨率 1920 * 1080, 计算可得对角线的设备像素为 2205.5.
5.5 * 401 = 2205.5
关系二:
逻辑像素(CSS 的 px) = 设备像素 * 缩放因子
举例:
iphone6 逻辑像素为 375 * 667, 分辨率为 750 * 1334, 缩放因子为 2
1 个逻辑像素(1px) = 设备宽度的 1/375
1 个设备像素 = 设备宽度的 1/750
1/375 = 1/750 * 2
以上参考: 1px 究竟是多大
由公式得出的结论
PC 端分辨率一样的情况下, 屏幕尺寸越大, 显示的越模糊(因为 dpi 越小).
举例说明:
我们的台式机电脑屏幕一般是 32 英寸, 分辨率为: 1920 * 1080. 而一般笔记本是 15.6 英寸, 分辨率也是: 19201080 的. 由公式一: 当分辨率一样时, 设备尺寸越大, 像素密度越小 *. 所以 32 寸的台式电脑看上去模糊一些.
相同分辨率, 相同缩放因子情况下, 不同设备尺寸下, 表现是一致的
举例说明:
平时我们在 pc 上 24 英寸的电脑上开发的网页直接写的 (px), 在不做任何兼容处理的情况下, 在 15.6 英寸的笔记本上也能正常显示. 由公式二: 因为一般 pc 端, 默认情况下缩放因子为 1(Windows.devicePixelRatio = 1), 分辨率也一样(1920 * 1080), 那么得到的逻辑像素(CSS 的 px) 也是一样的. 所以你在分辨率一样的情况下, 在大屏电脑上设置的 100px, 在小屏电脑上也是 100px. 只是他们表现出来的大小不一致, 小屏上面的 1px 更小.
如何将 pc 网页放到手机上展示?
我们可以调整网页在移动端上的缩放比例, 这个值就是 viewport. 默认情况下, 移动端浏览器会将 viewport 宽度设为 980px(也有可能是 1024px 或其它值), 也就是说 1px = 设备屏幕宽度的 1/980. 这跟缩放因子没有任何关系.
这时的 1px 非常小, 所有的元素都变得非常小, 移动端浏览器之所以这么做, 是为了尽可能完整的显示 PC 端的网页, 然后允许用户通过缩放来查看细节.
显然体验就别的特别差了, 很多本来就比较小的元素看都看不清了.
第二种方式是我们设置一个适当的缩放比例. 一般我们这样设置:
<meta name="viewport" content="width=device-width">
那么对于 iphone6 来说根据公式: 1px = 1/750(分辨率) * 2(缩放因子) = 1/ 375. 显然比刚才的 1/980 大了不少, 那么我们的元素如果还是按照原来的 px 去设置, 那么屏幕肯定展示不下去了, 这时候, 如果我们的元素的 px 值能根据 1px 的大小是动态调整, 我们的网页就完美了, 这时候 em,rem 就派上用场了.
em 是什么?
上面提到, 想让我们的网页在不同分辨率的设备 (移动端) 上正常显示, 最好我们的元素长宽, 外边距, 内边距等都是动态的
方式一:
上面说到, 我们在移动端一般这样设置:
<meta name="viewport" content="width=device-width;initial-scale=1">
这个时候我们 1px 的大小就已知, iPhone6 上为: 1px = 1/750(分辨率) * 2(缩放因子) = 1/ 375. 既然 1px 的大小固定了, 那么我们只能动态改变一个元素设置的 px 了, 比如说在 iPhone8 上是 120px; 而在 iPhone6 上需要是 100px. 这时候我们可以用 JS 去动态计算, 根据屏幕大小. 但是显然很麻烦, 需要对每一个元素的长宽, 内边距, 外边距都需要调整, 这显然是一个巨大的工程.
这时候我们就可以用到 em 这个单位了, em 单位的名称为相对长度单位, 是根据它父元素的字体大小来计算的, 一般默认情况下: 16px = 1em. 如果父元素 font-size:16px, 子元素 margin:0.8em. 那么得到的大小就是: 0.8 * 16 =12.8. 当所有单位都采用 em 时, 我们只需要改变 body 的 font-size, 那么其他子元素宽度就能动态变化了, 显然方便很多.
rem 是什么?
'rem'是'css3'新增的一个相对长度单位, 它的出现是为了解决 em 的缺点, em 可以说是相对于父级元素的字体大小, 当父级元素字体大小改变时, 又得重新计算. rem 出现就可以解决这样的问题, rem 只相对于根目录, 即 html 元素. 有了 rem 这个单位, 我们只需要调整根元素 HTML 的 font-size 就能达到所有元素的动态适配了, 附上一段常用适配代码:
- /**
- * ================================================
- * 设置根元素 font-size
- * 当设备宽度为 375(iPhone6)时, 根元素 font-size=16px;
- * ================================================
- */
- (function (doc, win) {
- var docEl = win.document.documentElement;
- var resizeEvt = 'orientationchange' in Windows ? 'orientationchange' : 'resize';
- var refreshRem = function () {
- var clientWidth = win.innerWidth
- || doc.documentElement.clientWidth
- || doc.body.clientWidth;
- console.log(clientWidth)
- if (!clientWidth) return;
- var fz;
- var width = clientWidth;
- fz = 16 * width / 375;
- docEl.style.fontSize = fz + 'px';// 这样每一份也是 16px, 即 1rem=16px
- };
- if (!doc.addEventListener) return;
- win.addEventListener(resizeEvt, refreshRem, false);
- doc.addEventListener('DOMContentLoaded', refreshRem, false);
- refreshRem();
- })(document, Windows);
总结
逻辑像素(CSS 的 px) = 设备像素 * 缩放因子
为了移动端更好的适配我们引入了 em 和 rem 这 2 个动态单位
em 的大小与父元素的 font-size 有关, rem 的大小与根元素 HTML 的 font-size 有关
一般在移动端我们会使用 JS 动态计算跟节点 HTML 的 font-size 来达到自适应的目的.
来源: http://www.jianshu.com/p/bcb2073b68ee