前端经典的em,rem,还有像素概念的问题,我发现很多说法都不统一,怎么说的都有,搞得我都有点不好抄统一的面试回答了。
干脆这里结合自己的理解,统一整理下,以便防止面试时候混乱。
正文
关于像素问题,几乎提到移动端适配这方面,这些基础概念就是在面试中绕不开的。
看了很多面试中都提到相关的问题,各种说法混乱无比,索性自己这里一把梭,把所有的概念都整理一下。
分辨率
我们实际开发中常说分辨率,但开发中说的内容可能指向的是不一样的内容。
物理分辨率
指的是显示屏的最高分辨率,又称标准分辨率。
屏幕实际存在的像素行数乘以列数的数学表达方式,是显示屏固有的参数,不能调节,其含义是指显示屏最高可显示的像素数。
我们实际使用过程,分辨率是可以改变的,比如我们手动将1920 * 1080的屏幕换成1600 * 900的分辨率,屏幕会按照你调整的要求,重新将屏幕切割为1600 * 900的像素点阵,形成新的分辨率。
不过,此时屏幕实际的物理分辨率依然还是1920 * 1080,这是屏幕自己固有的设备像素大小,并非我们可以手动调整的。
我们平时说的时候习惯性的说的分辨率,多数情况下都是指代最高分辨率,没什么人提你当前屏幕的分辨率是多少。
像素密度
正常来说,像素越大肯定是越清楚,但是这前提是要加个限定条件,那就是屏幕实际的大小要一样。
不然,物理分辨率同样是1920 * 1080的屏幕,一个尺寸是32寸,一个屏幕是100寸,实际显示效果确实一样的话,这怎么可能呢?
这里,就要引入一个概念:像素密度,ppi(pixels per inch)。
像素密度,表示沿对角线每英寸长度的像素数目(单位是dpi),越大显示的越细腻。
通过上边的例子,我们应该很快就能明白,像素密度的含义。
物理像素
物理像素(px:physical pixel)又可以称为设备像素(dp:device pixel)
我们以实际设备屏幕举例,我们说的1920 * 1080的屏幕,实际上就是在说:宽度方向有1920个像素点,长度方向有1080个像素点。
三者关系
设备尺寸 × 像素密度 = 物理分辨率(设备像素)
这里举个例子:
iphone6s 对角线长度为5.5 英寸,像素密度401 dpi,分辨率 1920 * 1080,计算可得对角线的设备像素为2205.5。
5.5 * 401 = 2205.5
这里说明白了这三者的关系,我们才好说明白接下来CSS的像素概念,即逻辑像素。
CSS像素
CSS 的像素单位,其尺寸大小是相对的,也有称其为独立像素的,这里为了避免大家混乱,下边统一称呼CSS的像素为逻辑像素。
逻辑像素
提到逻辑像素(logical pixel),也可以称为设备独立像素(dip : device independent pixel)。
当然,这两个名词我们大多数开发者可能都会陌生,实际上这里就是我们平常用到的CSS样式的像素单位。
物理像素与逻辑像素的关系
很多人这时候估计平时没有遇到过相关概念,所以一时间会有些懵,难道物理像素和逻辑像素有什么不同吗?难道我写了个100 * 100 的box,在小屏幕上就不是100 * 100了?
答案是:不是的。
1 | .box { |
比武我们这里写了一个100 * 100的box,假设在物理分辨率为100*100的屏幕上,它以100 * 100的方式展示,1个逻辑像素,用1 * 1个物理像素来表示。
而在 400 * 400 的屏幕上,我们同样让这个BOX达到充满屏幕的效果,那就需要4 * 4个物理像素来表示。
后者因为用更多的物理像素来展示,所以看起来更清晰,更精细。
设备像素比
我上边这个例子说的有个问题,为什么在有点屏幕上要以物理像素:css逻辑像素 = 1 :1 的比例展示,有的要以 4: 1的概念展示呢?
这里要引入一个概念:设备像素比(dpr : device pixel ratio)。不过这个说法也很混乱,我看很多整理的说法,有的说缩放比,也有说缩放因子的。
实际上,这就是物理像素与逻辑像素的比例概念。
我们这里为了接下来不混淆概念,统一就叫设备像素比。
1个css的逻辑像素,用更多的物理像素表示,那当时是比例越高,越清晰喽,如下例子。
1 | 标清屏:dpr = 2 / 2 = 1 |
因此,设备像素比越高,我们看到的网页也就越清晰,这也是为什么有时候我们看到有些手机实际屏幕很小,但看到页面的效果却很清晰。
屏幕虽小,但是实际物理分辨率和大屏一样,因此同样的网页,在更高的设备像素比的设备上显然看着更清晰,更细腻。
我们经常在设计师手中拿到的UI稿件,肯定会看到@1X,@2X,@3X,实际上就是这个就是指设备像素比。
tips:逻辑像素相对于设备像素的放大比例,可通过window.devicePixelRatio获得,pc上可以用个个性化来设置,但二者并不完全等同。
禁用缩放
提到上边的设备像素比的概念,有人可能会有疑问,按照这么说,岂不是我把页面用手势捏一下,就能改动页面的设备像素比?
是的,用户在移动端可以随意通过手势缩放网页,为了防止用户随意控制,我们便有了如下的操作。
1 | <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> |
相对单位
因为不同设备的的dpi不同,有时候PC上看上去非常正常的页面,放在手机端可能就显得不正常。
为了做各端的适配,于是前端衍生出了一种概念,相对单位。
em
上面提到,想让我们的网页在不同分辨率的设备(移动端)上正常显示,最好我们的元素长宽,外边距,内边距等都是动态的。
上面说到,我们在移动端一般这样设置:
1 | <meta name="viewport" content="width=device-width;initial-scale=1" > |
这个时候我们1px的大小就已知,iPhone6上为:
1 | 1px = 1/750(分辨率) * 2(设备像素比) = 1/ 375。 |
既然1px的大小固定了,那么我们只能动态改变一个元素设置的px了,比如说在iPhone8上是120px;而在iPhone6上需要是100px。
这时候我们可以用js去动态计算,根据屏幕大小。
但是显然很麻烦,需要对每一个元素的长宽,内边距,外边距都需要调整,这显然是一个巨大的工程。
这时候我们就可以用到em这个单位了,em单位的名称为相对长度单位,是根据它父元素的字体大小来计算的。
一般默认情况下:16px = 1em,这里要插一嘴,有的远古面试官经常会问:为什么1em要等于16px?
因为浏览器默认的字体大小都是16px,所以没有重新设置浏览器默认字体大小的话1em就等于16px。
在页面里要用到em作为单位的话,默认的
1em=16px
会使得在计算他们转换的值时非常不方便,比如我要把一个块里面的内容字体大小设置成18px,但我只想用em做为单位,那么情况就会这样,1em=16px,1px=0.0625em
,得18px=1.125em(0.0625em*18)
。这太麻烦,所以为了简化px和em之间的换算,需要在body里定义
font-size:62.5%
,即将浏览器初始化为即1em=10px
,这样的话,上面的font-size:18px
就等于font-size:1.8em
。
计算公式:1/父元素font-size值*需要转换的px=em值 (PS:父元素font-size的单位没有关系,无论px还是em)
这是早期的适应方式,当所有单位都采用em时,我们只需要改变body的 font-size,那么其他子元素宽度就能动态变化了,显然方便很多。
rem
rem是CSS3新增的一个相对长度单位,它的出现是为了解决em的缺点,em可以说是相对于父级元素的字体大小,当父级元素字体大小改变时,又得重新计算。
rem出现就可以解决这样的问题,rem只相对于根目录,即HTML元素。
有了rem这个单位,我们只需要通过JS调整根元素html的font-size就能达到所有元素的动态适配了,这里附上一段常用适配代码:
1 | /** |
vh,vw
vw ,就是根据窗口的宽度,分成100等份,100vw就表示满宽,50vw就表示一半宽。
vw 始终是针对窗口的宽,同理,vh
则为窗口的高度。
这里的窗口分成两种情况
- 在桌面端,指的是浏览器的可视区域
- 移动端指的就是布局视口
像vw
、vh
,比较容易混淆的一个单位是%
,不过百分比宽泛的讲是相对于父元素,而vw
、vh
相对的是指代当前窗口。
适配方案分析
无论是哪种方案,本质上都是为了解决移动端适配的问题。
这里本来打算自己整理一下各种方案的优劣,没想到有人已经整理好了,而且非常详尽:一次搞懂数据大屏适配方案 (vw vh、rem、scale)。
虽然是数据大屏的方案整理,但是已经够用了。
方案 | 实现方式 | 优点 | 缺点 |
---|---|---|---|
vw vh | 1.按照设计稿的尺寸,将px 按比例计算转为vw 和vh |
1.可以动态计算图表的宽高,字体等,灵活性较高 2.当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况 | 1.每个图表都需要单独做字体、间距、位移的适配,比较麻烦 |
scale | 1.通过 scale 属性,根据屏幕大小,对图表进行整体的等比缩放 |
1.代码量少,适配简单 2.一次处理后不需要在各个图表中再去单独适配 | 1.因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况 2.当缩放比例过大时候,字体会有一点点模糊,就一点点 3.当缩放比例过大时候,事件热区会偏移。 |
rem + vw vh | 1.获得 rem 的基准值 2.动态的计算html根元素的font-size 3.图表中通过 vw vh 动态计算字体、间距、位移等 |
1.布局的自适应代码量少,适配简单 | 1.因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况 2.图表需要单个做字体、间距、位移的适配 |
结语
这些基础概念,如果不是深入研究移动端适配的人,应该不会去深入了解,毕竟这都算是以前的老古董知识了。
实际开发中,移动端大多数中小厂商为了节省成本,应该是用Uni-app一把梭,直接用rpx完成移动端单位的适配。
甚至有些项目为了图省事的,直接用px糊弄了事,很少有人去实际操心适配的问题,毕竟多数都是为了赶工期。
这里今天整理一下,也算是梳理以前有些混乱的知识体系,把以前脑海中各种混乱的名称做了个整合,心情也算是颇为舒畅。
不过,关于移动端的适配,我这里只是浅浅聊了一下,后续有时间会逐步整理相关的知识,防止面试官去面试这些乱七八糟的考验广度的面试题。
参考
【CSS】一文搞懂 em、px、rem、vh、vw 的区别!