准备工作:
两个像素:设备像素+css像素
设备像素:
绝对单位,设备像素即设备的物理像素,对于每个设备来说,其设备像素是固定的,它是每个设备能控制显示的最小单位。通常我们所说的1920x1080像素分别率就用的是设备像素。
css像素:
适用于web编程,是前端开发在描述css样式时经常用到的像素单位。比如,设置某个div的宽度为width:200px,这个就是css像素,是一种抽象概念,实际上并不存在。
页面的缩放:
当用户放大或者缩小页面时,改变的是css像素,而设备像素不会发生改变
如:页面中一个div,它的宽度是200px,当用户操作页面,放大两倍,此时一个css像素的面变成了4个设备像素的面积:宽放大2倍x高放大两倍
页面缩放比例(zoom level)= screen.width / window.innerWidth (一般情况下可以这么计算)
设备像素比(DPR):
在页面缩放比为1的情况下,设备像素比(DPR) = 设备像素个数 / 视觉视口css像素个数(device-width)
对于不同的设备来说设备像素比是不一样的。在早期iphone的DPR值是等于1的,但是后来引入了高密度屏幕,即为了更清晰的展示画面,在有限的设备空间内引入了更多的设备像素。所以后来iphone设备的DPR就改变了,值一般为2
场景再现:
移动端需求:给你一个750px的设计稿,上面画了一个200px的矩形框。
既然是写移动端页面,作为一名前端开发者,我想你们首先就会在里面敲下这样一句话:
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
看上去只有那么熟悉了。这句话什么意思?它有什么作用呢?别着急,我们先来理解下viewport这个概念。
viewport:
viewport即视口,它的作用是限制页面的根元素
在PC端,视口可以看成只有一个,即我们所看到的页面窗口,它的大小由浏览器窗口来决定
但是在M端视口分为两类:视觉视口(visual viewport)和布局视口(layout viewport)
既然M端做了这样的划分,我们也可以对PC端采取同样的方式,即PC端viewport就是PC端的visual viewport
所以,对于PC端来说,根元素的大小就可以由visual viewport来确定了。那么,怎么计算呢?下面分情况给出相应的计算方式:
1:浏览器没有出现(横向、纵向)滚动条且没有人为的去设置元素的宽高(html的宽高可以人为的去设置,但是一般情况下我们不建议这样做):
html的宽度 = document.documentElement.clientWidth = document.documentElement.offsetWidth = window.innerWidth
2:浏览器出现滚动条且没有人为的去设置元素的宽高:
html的宽度 = document.documentElement.clientWidth = document.documentElement.offsetWidth = window.innerWidth - 滚动条的宽度
3:人为设置了的宽度时:
html的宽度 = document.documentELement.offsetWidth
如此,PC端就可以按照其viewport的尺寸进行页面的布局
有了上面的基础,我们接下来看看M端页面。M端较之于PC端,一个显然的不同就是设备的尺寸。M端的屏幕宽度大多<=400px,不像PC端那样,动不动就是上千像素。这样PC端的页面到了移动端,可谓是不堪入目
在没有做M页面优化的情况下,PC端页面放到M端时,为了让你看清整个页面,强行把里面的内容进行缩放,以至于模糊不清,简直无法直视
如何解决M端设备尺寸太小的问题呢:
既然移动端的视觉视口太窄(浏览器的宽度)而不能满足css布局的需求,那么就想办法弄一个更宽的视口出来,满足M端布局需求。此时,layout viewport应运而生。
布局视口比视觉视口要宽的多,M端就是根据布局视口来进行css布局的。而且在M端,元素的大小是由布局视口来确定的,就像我们之前谈到的PC端和视觉视口的关系那样。那么,布局视口到底有多大呢,以及他是怎样去计算的呢?
对于M端来说,其布局视口的大小取决于浏览器厂商,一些常见的布局视口取值如下表所示:
跟PC端有点类似,布局视口的大小可有下面的方式取得:
布局视口的宽度 = document.documentElement.clientWidth
布局视口的高度 = document.documentElement.clientHeight
我们想要怎样一种效果呢?应该是这样:我们不想页面出现滚动条,而且想要页面所有的内容都呈现在我们的视野范围内。即要是我们能够自己去控制M端布局视口的大小就好了,让它以一个用户比较舒适的大小呈现在屏幕上,标签帮我们完成了这一举动,让我们继续看看吧。
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" user-scalable=no>
是不是很熟悉,对啦,我们在文章的开头时曾写过。关于viewport我们不再解释,下面简单说一下content里面的内容。content属性的值是一个字符串,字符串里面的内容是由逗号隔开的名值对,一共5个:
- width:布局视口的宽度,可以自己设定准确的值如width=300,也可以是一些特殊值,如width=device-width,顾名思义就是设备的宽度
- initial-scale:设置页面的初始缩放程度,可以是小数
- minimum-scale:设置页面的最小缩放程度
- maximum-scale:设置页面的最大缩放程度
- user-scalable: 是否允许用户对页面进行缩放
于是我们这样设计代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>移动端页面开发</title> <style> * { margin: 0; padding: 0; } .weekend { width: 200px; height: 200px; background-color: green; } </style> </head> <body> <div class="weekend"></div> </body> </html>
咋一看,哎,不对呀,矩形框的宽高没有问题,但是设计稿上的设备宽度是750,而浏览器显示的宽度则是375,这是怎么回事呢?
其实,设计稿是按照设备像素去设计的,所以在页面缩放比为1的情况下,根据公式:
DPR = 设备像素/视觉视口css像素个数(device-width)
在iphone7上DPR=2,所以2个css像素等效于2个设备像素,所以对于矩形框的宽度,应该设为200/2=100px
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>移动端页面开发</title> <style> * { margin: 0; padding: 0; } .weekend { width: 200px; height: 200px; background-color: green; } </style> </head> <body> <div class="weekend"></div> <script> var scale = 1/window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=device-width, initial-scale=' + scale + ', user-scalable=no') </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content=""> <title>移动端页面开发</title> <style> * { margin: 0; padding: 0; } .weekend { width: 2rem; height: 2rem; background-color: green; } </style> </head> <body> <div class="weekend"></div> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; </script> </body> </html>