是什么
1.css像素
css是一个不确定的物理像素,它是根据它所在的机型设备而决定的。
2.逻辑像素
设备独立像素也叫做逻辑像素,与css像素一样是一种虚拟的像素,它是操作系统定义的一种像素单位,应用程序将设备独立设备告诉操作系统,操作系统再将独立设备像素转为设备像素。
3.设备像素
显示屏是由无数个物理像素点组成的,通过控制每个像素点的颜色,从而可以在屏幕上显示不同的图案,设备像素是固定不变的。
4.DPR
设备像素与CSS像素之间的关系
设备像素比DPR = 设备像素/CSS像素
比如:设备像素比 = 分辨率(设备像素数如19201080) ➗ 设备独立像素数/CSS像素数(如1280610) 。iPhone 6 物理像素为 750 x 1334,理想视口 375 x 667 ,DPR = 2
详解
现在我们对CSS像素和设备/物理像素还没有比较清晰认识,请继续看下面解释:
pc端1个css像素用一个物理像素表示
我们写样式时一个像素记作1px,但是css的px和物理像素是一一对应的吗,是同样的概念么?在pc端是这样的,因为屏幕足够大,一个css像素用一个物理像素来显示,完全可以,pc端默认情况下一个css像素就对应着一个物理像素,但是有没有发现你把分辨率调小以后,显示的内容变大了,但是显示器的物理像素肯定不会变啊,这时候其实就是一个css像素对应着若干个物理像素了,这个是与用户设置有关。
m端 一个css像素对应多个物理像素
移动设备大小是有限的,而且分辨率不低,甚至比pc端更高,也就是可以显示的物理像素更多,如果和pc端一样,一个css的px和物理像素一一对应,可以想象,显示的内容有多小。这样肯定是不行的,解决这个问题,我们可以很自然的想到,那在移动设备上就别一一对应了,一个css的px对应多个物理像素吧,这样就不至于显示的内容过小了,实际上移动设备也是这么做的,你在开发时写的px和最终渲染显示的物理像素数不是一比一的,可能一个px对应2个物理像素,可能3个物理像素,设备显示的物理像素数和你css的px数的比值就叫做设备像素比(device pixel radio),简称dpr。好了,这样显示内容过小的问题就解决了。
dpr越高越好,当然需要2倍,3倍图来更高清
有了dpr之后,有一个问题就是同样的一张图片,我设了宽高的px数,那么在dpr为1的设备上,和dpr为2的设备上显示的效果是一样的,1个px在dpr为1的设备上会用1个物理像素来显示,在dpr为2的设备上会用2*2个物理像素来显示,这样dpr高的优势就体现不出来了,我设备比他的好,你给我的体验是一样的,可能有些用户不爽,我们可以区分对待,对于高dpr的设备,用物理像素更多的高清图片来替代,也就是2x图,3x图等等。
Retina高清屏
其实在很久以前,的确是没区别的,CSS里写个1px,屏幕就给你渲染成1个实际的像素点,DPR=1,多么简单自然~后来苹果公司为其产品mac、iPhone以及iPad的屏幕配置了Retina高清屏,也就是说这种屏幕拥有的物理像素点数比非高清屏多4倍甚至更多。如果还按照DPR=1进行展示,那么同一张图片在高清屏上面显示的区域面积会是非高清屏的1/4,这样的话由于图片在屏幕上的展示面积大大缩小,也会导致出现“看不清”的问题。苹果公司既然推出了Retina技术,那么这种技术带来了高清展示福利的前提下也要解决“DPR=1”的问题。怎么解决呢?DPR!=1。苹果公司经过一系列技术使用4个乃至更多物理像素来渲染1个逻辑像素,这样一来,同样的CSS代码设置的尺寸,在Retina和非Retina屏幕上看起来大小是一样的,但在Retina屏幕上要精细得多。在Retian屏上,DPR不再是1,而是大于1,比如2(iPhone 5 6 7 8)或3(iPhone 6 Plus等一系列Plus)或者为非整数(一些Android机),说不定还会涨。
举个例子 苹果6的DPR是2
iPhone 6的物理像素上面已经说了,是750 * 1334,那它的逻辑像素呢?我们只需在iPhone 6的Safari里打印一下screen.width和screen.height就知道了,结果是 375 * 667,这就是它的逻辑像素,据此很容易计算出DRP为2。当然,我们还可以直接通过window.devicePixelRatio这个值来获取DRP,打印结果是2,符合我们的预期。
逻辑像素css像素与物理像素
1px边框问题
在苹果的带动下,Retina技术在移动设备上已经成了标配,所以前端攻城狮必须直面如下事实
-
你想画个1px的下边框,但屏幕硬是塞给你一条宽度为2—3个物理像素的线。
-
你没法像安卓或iOS的同事那样直接操纵物理像素点。
1px边框问题解决方式:
- border-image 图片
- background-image 渐变
- box-shadow 等
- 参考:segmentfault.com/a/119000001…
- 伪元素+transform”对边框进行缩放;scaleY(0.5)
- 用JS根据屏幕尺寸和dpr精确地设置不同屏幕所应有的rem基准值和initial-scale缩放值。
混合开发使用rem
由于 em 存在对父元素继承的问题,当改变字体大小时涉及的继承关系就变得复杂起来。
rem 是相对于根元素 字体尺寸的大小。如 文本大小设为 font-size: 10px,则 1rem = 10px。使用 rem 设置字体则简单了很多。
移动设备的宽度是各种各样的,每个设备的dpr也不同,换句话说就是不同设备每一行的物理像素数不同,能显示的css的px数也不同,如果我们写死px的话,那么后果就是同样的px,在不同设备中显示的行数不同,这样整个排版就乱了,想想有啥解决的思路没? 分析一下造成显示效果不同的原因就是设备宽度不同,你可能会问,那dpr呢,其实与dpr一点关系都没有,想象一下2个宽度为1000个物理像素的设备,一个dpr为1,一个dpr为2,那么在我们看来不过一个是1000px,一个是500px而已,在这里我们感知不到dpr。那么设备宽度不同怎么做适配呢,其实很容易的会想到,每个设备每行显示的px数不同,你写死px数的话,那肯定显示的效果不一样,所以,不能写死,要动态的计算。对,实际上也是这么解决的,那怎么计算呢,很简单,你把一个设备的样式写好了,其他的根据设备的宽度(px数)的比,来动态计算就行了。
rem就是解决这个问题的,rem不是具体的px,rem具体显示多少像素,是根据根元素的font-size来计算的,比如说你设置了1.2rem,根元素的font-size是100px,那么这个元素动态算出来的px数就是120px。不同宽度,设置不同px,这样就可以适配所有宽度的设备了。
方式一
具体代码是:(假设开发时我们适配的是iphone6,也就是375px的设备,我们开发时根元素font-size设为了100px)
var 根元素fontsize = 实际设备宽度 / 开发时设备宽度 * 开发时根元素font-size
document.documentElement.style.fontSize =
(document.documentElement.offsetWidth/375)*100 + 'px' ;
rem 介绍
rem是相对于根元素(html标签)的字体大小的单位。
核心思想:百分比布局可实现响应式布局,而rem相当于百分比布局。
实现手段:动态获取当前视口宽度width,除以一个固定的数n,得到rem的值。表达式为rem = width / n。
通过此方法,rem大小始终为width的n等分。
如何动态计算rem
// 动态为根元素设置字体大小
function init () {
// 获取屏幕宽度
var width = document.documentElement.clientWidth
// 设置根元素字体大小。此时为宽的10等分
document.documentElement.style.fontSize = width / 10 + 'px'
}
//首次加载应用,设置一次
init()
// 监听手机旋转的事件的时机,重新设置
window.addEventListener('orientationchange', init)
// 监听手机窗口变化,重新设置
window.addEventListener('resize', init)
理解:上面代码实现了,无论设备可视窗口如何变化,始终设置rem为width的1/10.即实现了百分比布局
以上代码需在dom之前写入(可放在head里面第一个script标签)
移动端加上meta标签
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
不用js动态计算,用css动态计算,不靠谱
html{
font-size:calc(100vw/7.5)
}