一、理论
1、像素理论
屏幕尺寸 |
---|
单位:英寸 ,1英寸=2.54厘米 |
指屏幕对角线的长度 |
物理像素和css像素 |
---|
物理像素是屏幕物理分辨率,比如1920*1080,每个物理像素点称为1像素 |
css像素是逻辑像素,一般1px等于1个物理像素点 |
因为现在不同设备分辨率也不一样,而且现在很多设备采用了高清屏,所以我们设计css时要避免使用px,转而多使用vh,rem和百分比,这样就会适配物理像素,以上提到的各种单位统称为css像素 |
比如,两个手机都是3.5英寸的手机,但是普通屏幕像素是480* 320px,高清屏是960* 640px,这时就衍生了一个单位PPI |
一般相同区域的像素点数,高清屏是普通屏4倍 |
PPI:像素密度或屏幕密度 |
---|
屏幕上每英寸可以显示的像素点数量,单位是ppi |
PPI与像素密度和屏幕分辨率有关 |


设备独立像素(密度无关像素) |
---|
计算机坐标系中的一个点 |
这个点可以代表一个可以由程序使用的虚拟像素(比如css像素),然后由相关系统转换为物理像素 |
这个概念很重要,是我们日后css像素转换为物理像素的关键 |
可以把设备独立像素看成是不同设备提供出来的接口,它用来对接应用的一些概念,比如浏览器中的css像素 |
只有当浏览器厂商对接上设备独立像素时,浏览器厂商设计的移动端规则才能起作用,否则采用默认规则 |
位图像素 |
---|
是栅格图像(png,jpg,gif等)的最小数据单元 |
只有1位图像素=1物理像素才能得到完美清晰的展示 |
不对应,会造成图片的失真,偏差越大,失真越严重 |
像素比DevicePixelRatio 简写为DPR |
---|
同一个方向上占满屏幕的物理像素 /同一个方向上占满屏幕的设备独立像素 |
设备物理像素和独立像素的比例 |
DevicePixelRatio=物理像素/设备独立像素 (官方定义) |
可以通过window.devicePixelRatio获取 |
通俗的讲就是同一个方向上占满屏幕的物理像素/同一个方向上占满屏幕的设备独立像素 |

如果iPhone6像素比为2,那么一个css像素占据多少个物理像素? |
---|
首先
像素比=2
那么按照官方的定义
物理像素/设备独立像素=2
物理像素=2*设备独立像素
非常容易混淆,这里它实际的意思是
像素比=同一个方向上占满屏幕的物理像素/同一个方向上占满屏幕的设备独立像素
物理像素= 2*横轴设备独立像素 * 2*纵轴设备独立像素
此时
你给物理像素不断的升倍,比如4*物理像素= 2*横轴设备独立像素 * 2*纵轴设备独立像素
那么就表示 一个独立像素=4个物理像素
这里如果你还不懂,往下看例子
如果
物理像素为750*1334
设备独立像素为375*667
(以上这些都是厂商设定好的)
那么
像素比 = 750/375 = 2 或1334/667 = 2 (同一个方向上占满屏幕的物理像素/同一个方向上占满屏幕的设备独立像素)
1设备独立像素=4物理像素(因为像素比是2,先看横向750/375=2,再看纵向1334/667=2,2+2=4)
当我们
写上meta标签后,并指定width=device.width
这样css像素就和设备独立像素链接了起来
此时
因为已经建立链接,那么设置css像素就会等同于设备独立像素
又因为
1设备独立像素=4物理像素
即
1个css像素占据iPhone6手机的4个物理像素
2、视口理论
布局视口 |
---|
我们pc端的网页尺寸远远比手机尺寸大,那么手机浏览器肯定要有一个容器来装,这个容器叫布局视口 |


视觉视口 |
---|
就是你通过手机屏幕看到的,你看到的内容是多少像素,这个视觉视口的大小就是多少,而布局视口一直不变,手机出厂的时候就固定了 |

总结布局视口和视觉视口 |
---|
布局视口决定你的页面布局,它永远就是一个固定的像素,页面尺寸超过,就看不到或者换行 |
视觉视口决定你能看到的内容,你所能看到的内容决定他的尺寸,它会随着你的缩放进行改变 |
布局视口的物理尺寸就是设备屏幕的尺寸 |
布局视口 的物理尺寸 中包含 的css像素 的个数是固定 的 |
视觉视口 的物理尺寸 中包含 的·css像素的个数是 不固定`的 |
用户没有缩放 的情况下,视觉视口 的物理尺寸等于布局视口 的物理尺寸 |
视觉视口可以完整的包住布局视口 |
视觉视口决定了物理像素和css像素的比例,因为缩放会放大页面,此时更少的css像素填充了物理像素 |
理想视口 |
---|
布局视口的默认宽度不是一个理想的宽度,对于我们移动设备来说,最理想的情况是 |
用户刚进入页面时不需要缩放,但只有专门为移动设备开发的网站,才有理想视口这一说 |
只有页面中加入viewport的meta标签,理想视口才能生效 |
< meta name=“viewport” content=“width=device-width,initial-scale=1.0”> |
上面的代码表示布局视口的宽度应该与理想视口保持一致,并且初始缩放为1 |
理想视口包含的css像素个数等于独立设备像素值 |
定义理想视口是浏览器厂商的工作,不同浏览器有不同的理想视口 |
浏览器理想视口大小取决于设备,同一款浏览器在不同设备上的理想视口不同 |
3、获取视口尺寸
一、pc端,只有一个视口,它会随着你的放大缩小而改变,影响布局
document.documentElement.clientWidth
document.documentElement.clientHeight
二、移动端(以下都是获取宽度,获取高度将Width换成Height即可)
var layout = document.documentElement.clientWidth;
var visual = window.innerWidth;
var dream = screen.width;
4、viewport详解
完美视口+不让用户缩放,以后直接来复制这个就可以了 |
---|
<meta name = viewport" content "width=device-width,height=device-height,user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />





5、等比问题
一个60*36的图片,想要放在DPR=2的设备上,应该用多大的css容器包裹呢?
因为一张图片最好的样子是一个物理像素显示一个位图像素,所以我们需要通过计算,让一个css容器的大小尽量使图片每一个位图像素对应一个物理像素
首先根据像素理论,DPR = 物理像素/设备独立像素
因为我们开发移动端都会将css绑定到设备独立像素上,所以css像素等于设备独立像素
则:css像素=物理像素/DPR
那么我们需要的物理像素是60*36,已知DPR=2,则css容器像素为
css像素=60/2 ==》 30
css像素=36/2 ==》 18
最终,我们应该使用
30*18的容器来包裹这张图片
那么这时候你会问,那如果DPR=2的设备,物理像素有的少有的多怎么办
DPR=2的设备,我们统一采用iPhone6来作为设计初稿,因为是最标准的
而其它DPR=2的设备都比iPhone6小,我们就不用担心了,图片不会失真,只会锐化,基本看不出来
那如果是DPR=3的呢?
这时候就需要重新设计了,一般设计师会将图片设计两套,一个是给DPR=2的设备用的,一个是给DPR=3的设备用的
因为DPR=3的设备比iPhone6大,图片就会失真了
一样的通过公式来算
css像素 = 物理像素/DPR
css像素 = 60/3,css像素 = 36/3
通过规律可以发现
DPR=2的设备想要让图片完美显示,只需要设置容器大小为图片的一半,60*36的图片,设置css容器为30*18
DPR=3的设备就是三分之一,60*36的图片,设置css容器为20*12
二、适配
1、rem适配方案
em和rem |
---|
em:是自身的font-size大小,1em=自身font-size,如果你设置font-size=10px,那么1em=10px |
rem:是根标签的font-size大小,1rem=根标签font-size |
rem有什么用 |
---|
我们需要在不同尺寸移动端设备上还原设计稿比例,那么就得给每一个移动设备设置一套尺寸,因为涉及到像素比和物理像素 |
而有了rem,我们只需要为不同尺寸的移动端设置不同的font-size(根标签的),就可以达到对应的尺寸 |
优点:完美视口,体验好 |
缺点:像素与rem转换太过复杂 |
谷歌览器字体尺寸 |
---|
谷歌浏览器默认大小16px,最小12px |
ie6所有元素最小就是16px,非常麻烦,最好的解决办法,就是设置如果是ie6就设置font-size:0; |
但是这样也只能最小到2px,而永远到不了1px |
rem适配,使用1rem 直接让容器的宽度 在不同设备上都正好填满屏幕 |
---|
直接换不同设备查看效果时,要记得刷新,否则无法获取,因为我js使用的是onload事件 |
对于实际开发我们经常取document.documentElement.clientWidth/16 来适配 |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<style type="text/css">
*{
margin: 0;
}
div{
width: 1rem;
height: 1rem;
background-color: #09D5FC;
}
</style>
</head>
<body>
<div></div>
</body>
<script type="text/javascript">
window.onload=function(){
let html = document.querySelector("html")
html.style.fontSize = document.documentElement.clientWidth+"px"
}
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<style type="text/css">
*{
margin: 0;
}
div{
width: 16rem;
height: 1rem;
background-color: #09D5FC;
}
</style>
</head>
<body>
<div></div>
</body>
<script type="text/javascript">
(function(){
let styleNode = document.createElement("style");
let width = document.documentElement.clientWidth/16;
styleNode.innerHTML = "html{font-size:"+width+"px;!important}";
document.head.appendChild(styleNode)
})()
</script>
</html>
2、viewport适配方案
只要实现将任何设备的布局视口的宽度调整为设计稿的宽度就达到了适配 |
---|
优点:简单,所量即所得 |
缺点:没有完美视口 |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width" />
<title></title>
<style type="text/css">
*{
margin: 0;
}
div{
width: 750px;
height: 1rem;
background-color: #09D5FC;
}
</style>
</head>
<body>
<div></div>
</body>
<script type="text/javascript">
(function(){
let targetWidth = 750;
let scale = document.documentElement.clientWidth/targetWidth;
let meta = document.querySelector("meta[name='viewport']");
meta.content="initial-scale="+scale+",minimum-scale="+scale+",maximum-scale="+scale+",user-scalable=no";
})()
</script>
</html>
剩下百分比适配,或者主体内容固定,其它流体布局这种适配方案,就太简单了,而且效果也不太好 |
---|
三、1物理像素实现
1、通过dpr缩放,使用rem来规定1px=1物理像素
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
div{
width: 16rem;
height: 1px;
margin-top: 1rem;
background-color: black;
}
</style>
</head>
<body>
<div></div>
</body>
<script type="text/javascript">
(function(){
let dpr = window.devicePixelRatio || 1;
let styleNode = document.createElement("style");
let width = document.documentElement.clientWidth*dpr/16;
styleNode.innerHTML="html{font-size:"+width+"px !important}";
document.head.appendChild(styleNode);
let scale = 1/dpr;
let meta = document.querySelector("meta[name='viewport']");
meta.content="width=device-width,initial-scale="+scale+",minimum-scale="+scale+",maximum-scale="+scale+",user-scalable=no";
})()
</script>
</html>
2、通过@media来适配,这种就是典型的为了适配写多套样式,也是最简单,但是最麻烦的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
div{
width: 100%;
height: 1px;
margin-top: 1rem;
background-color: black;
}
@media only screen and (-webkit-device-pixel-ratio:2){
div{
transform: scaleY(.5);
}
}
@media only screen and (-webkit-device-pixel-ratio:3) {
div{
transform: scaleY(.3333333333333333);
}
}
</style>
</head>
<body>
<div></div>
</body>
</html>
四、移动端事件
1、获取dom节点
<script type="text/javascript">
let div = document.querySelector("#div");
let divList = document.querySelectorALL("div");
let divByClass = document.getElementsByClassName(".div");
divList = document.querySelectorAll("div");
</script>
2、触屏事件
<script type="text/javascript">
window.onload=function(){
let div = document.querySelector(".div");
div.addEventListener("touchstart",function(){
console.log("手指触摸事件")
})
div.addEventListener("touchmove",function(){
console.log("手指滑动事件")
})
div.addEventListener("touchend",function(){
console.log("手指放开")
})
}
</script>
移动端经常出现长按的情况,这时会选中文字然后触发不必要的事件,为了避免可以禁用默认事件 |
---|
<script type="text/javascript">
window.onload=function(){
let div = document.querySelector(".div");
div.addEventListener("touchstart",function(ev){
ev = event||ev;
ev.preventDefault()
console.log("手指触摸事件")
})
document.addEventListener("touchstart",function(ev){
ev = event||ev;
ev.preventDefault()
console.log("手指触摸事件")
})
</script>
3、多指列表
<script type="text/javascript">
window.onload=function(){
let div = document.querySelector(".div");
div.addEventListener("touchstart",function(ev){
ev = event||ev;
ev.preventDefault()
console.log("触发当前事件手指多少根",ev.changedTouches.length)
console.log("触发当前事件时元素上手指多少根",ev.targetTouches.length)
console.log("触发当前事件屏幕上有多少根手指",ev.touches.length)
})
}
</script>
4、移动端常见问题
1、禁用点击电话号,邮箱自动拨号和跳转
<meta name="format-detection" content="telephone=no,email=no"/>
<a href="tel:110">110</a>
<a href="mailto:95656@qq.com">95656@qq.com</a>
2、解决移动端加圆角按钮直接变成圆
<style type="text/css">
input{
width: 50px;
height: 50px;
border-radius: 5px;
-webkit-appearance: none;
}
</style>
<input type="button" value="按钮" />
3、font boosting,解决移动端觉得字太小自动帮你放大的问题
p{
font-size:24px;
max-height:999999px;/*解决问题*/
}
4、禁用长按选中文字功能
.txt {
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
}