CSS像素、物理像素、逻辑像素、设备像素比、PPI、Viewport
关于移动端适配,你必须要知道的

这篇主要介绍适配的相关知识点,不变的那种
至于经验类:
细看动画排坑技巧(1px问题、适配iPhonex问题、图片模糊问题
实践类:媒体查询、屏幕适应(百分比布局、缩放布局、rem自适应

设备像素/像素密度/设备像素比

指尖上行
**
设备像素
image.png

像素密度ppi
image.png

判断retina屏幕可以通过ppi判断,但更方便的是通过dpr判断

设备像素比dpr
js:
Window.devicePixelRatio 获取当前设备的dpr
css:
image.png
image.png

  1. @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){
  2. }

关于市面上各个手机的 ppi、dpr等可以在 http://screensiz.es/ 这里查看

一般来说,物理像素=设备独立像素(dp)设备像素比
设备独立像素可以在开发者工具看到 image.png
但是也有例外:
iPhone 6、7、8 Plus 实际物理像素 = 1080 x 1920,设备独立像素=414 x 736,设备像素比为3
设备独立像素
设备像素比 = 1242 x 2208

实际上,手机会自动把1242 x 2208个像素点塞进1080 * 1920个物理像素点来渲染,我们不用关心这个过程,1242 x 2208被称为屏幕的设计像素。我们开发过程中也是以这个设计像素为准。

**在iOSAndroidReact Native开发中样式单位其实都使用的是设备独立像素。
在写CSS时,我们用到最多的单位是px,即CSS像素,当页面缩放比例为100%时,一个CSS像素等于一个设备独立像素。

为了适配所有机型,我们在写样式时需要把物理像素转换为设备独立像素:例如:如果给定一个元素的高度为200px(这里的px指物理像素,非CSS像素),iphone6的设备像素比为2,我们给定的height应为200px/2=100dp

viewport

深入了解viewport和px
指尖上行

latout viewport

latout viewport:document.documentElement.clientWidth\document.documentElement.clientHeight
浏览器默认的窗口,在移动端设备为了不让pc页面因为viewport太窄而使页面错乱,一般将vp设置为较宽的,比如980px;在这样的窗口下手机呈现就像在pc上打开页面一样,只是手机是一个小小的框选出小小一部分展示给用户;
手机就像一个放大倍数为1的放大镜;

image.png

部分机型默认viewport大小:
image.png

那么手机框选的这个框到底有多大呢?
visual viewport:window.innerHeight\window.innerWidth
image.png

ideal viewport
这是一个理想的、抽象的视图,在此视图下,图片和文字无论什么设备、分辨率,看起来都会保持差不多的大小;
image.png

知道ideal port,我们的目标是将latout viewport设置成ideal viewport的宽度,此时如果页面缩放比例同时满足100%,那么此时 CSS像素 = 设备独立像素,理想视口 = 视觉视口
===》
让当前layout view 宽度=设备的ideal viewport宽度,同时不允许用户手动缩放

  1. <meta
  2. name="viewport"
  3. content="width=device-width, initial-scale=1.0,maximum-scale=1.0,user-scalable=0"
  4. >

device-width 即设备独立像素宽度
initial-scale=1.0 缩放是以ideal viewport作为参考,当设置initial-scale=1.0即缩放100%,言外之意也就是使得layout viewport=ideal viewport

image.png

当然 viewport也可以通过js动态修改

  1. == 使用document.write ==
  2. document.write('<meta name="viewport" content="width=变化值">');
  3. == 使用setAttribute ==
  4. <meta id = "test" name="viewport" content="width=device-width">
  5. var vp = document.getElementById('test');
  6. vp.setAttribute('content','width=变化值')

我们直观地理解一下viewport的重要性:

刚开始接触移动页面重构,是不是很迷惑应该按照多大的尺寸制作?320、640还是720?按照640的设计稿重构完页面,是不是还需要写其他尺寸来适配不同的屏幕大小?——这源于对viewport和px的不了解。

已经重构了好多移动页面,但是对为什么要按照640的大小来设计页面,不清楚答案。给元素赋予固定的像素值,但是奇怪的是在不同的手机里看起来都差不多大小,不需要另外去适配,真是太爽了。为什么?不知道耶。——这源于对viewport和px的不了解。

一个栗子:
image.png

机型iPhone4s 已知
image.png 手机分辨率:960*640
ppi:326
viewport默认:980px
ideal viewport/device-width:320px

iPhone4S如果不设置viewport,他就会默认是980px,就像把屏幕分成980份(不是屏幕分辨率的640px哦!)。
此时如果设置一个元素为100px*100px,看起来就是屏幕的100/980

iPhone4S如果设置viewport width=device-width(device-width 即设备独立像素宽度),他就会是320px,就像把屏幕分成320份(不是屏幕分辨率的640px哦!)。如果设置一个元素为100px*100px,看起来就是屏幕的100/320
image.png

即同样是设置元素100px,但是在不同的viewport渲染下,元素大小不一样。因为归根结底css里的px不是物理上的绝对长度,而是根据一个占比值。1px等于将屏幕分成无法分割的方格,最小的那个方格边长即为1px;
如果确定最小方格?取决于将屏幕怎么分
当viewport为浏览器默认时(大部分机型为980px)此时不同机型下的1px为屏幕的1/980
当viewport为device-width 设备独立像素宽度时, 此时不同机型下的1px又不同

所以归根结底,我们的适配不是为了在不同的机型上展示一样大小的元素,
而是将元素根据不同大小的屏幕适配成大致相同的比例;

比如一个眼睛,同样是眼睛,长在乐山大佛脸上就有1米长,长在人脸上就几十厘米,但是归根结底不变的是眼睛占脸的比例(不可能整个脸都是眼睛吧~

设置了viewport,width=device-width,以下机型的device宽依次为375px、360px、360px、320px。
image.png
咋来的?

iPhone6的屏幕分辨率是1334750px,ppi是326,所以系数是2x。那device-width就等于750/2=375px。 红米1s的屏幕分辨率是1280720px,ppi是312,所以系数是2x。那device-width就等于720/2=360px。

不管哪种尺寸的设计稿,重构都可以用一套方法制作好页面,如果是背景平铺(background-size:100%)、上面的元素px设置大小的话,没问题,能顺利适配其他手机的。如果是固定整体大小重构,再利用js判断屏幕大小进行页面缩放,也没问题,能顺利适配其他手机的。重要的前提是要设置好正确的viewport。

然而我们实际上并不是设置了viewport并配合px就能万事大吉的,事实证明使用设备独立像素只能保证元素在不同手机上显示的效果“类似”,但这并不能保证它们显示完全一致,我们需要一种方案来让设计稿得到更完美的适配

详情请见页面布局

布局方法论:百分比布局、rem适配布局、缩放布局、flexible方案、vh,vw方案
布局断点:媒体查询、基于内容断点

一般方法论和布局断点配合使用