移动端适配
基础知识
- 设备像素(物理像素)
- 屏幕尺寸和像素密度(PPI)
- CSS 像素(设备独立像素、逻辑像素)
- 像素比(DPR)
设备像素
设备像素就是指实际存在的像素,也就是设备的分辨率
屏幕尺寸和像素密度
英寸是一个长度单位,1 英寸(inch)等于 2.54 厘米(cm)。其次这里的 6.67 英寸指的是屏幕对角线的长度。
// 屏幕斜边的像素
const margin = Math.sqrt(Math.pow(1080,2)+Math.pow(1920,2));
console.log(margin); // 2202.9071700822983
console.log(margin/5.5); // 400.52857637859967 PPI
CSS 像素(设备独立像素、逻辑像素)
CSS 像素和设备像素 1:1 关系,1 个 CSS 像素对应 1 个设备像素,那么现在我修改这个比例,1 个 CSS 像素对应 2 个设备像素即可。
以前在做 PC 端网页开发的时候,由于 CSS 像素始终和设备像素是 1:1 的关系(不考虑缩放),所以给大家了一种错觉,以为 CSS 像素和设备像素就是 1:1 的对应关系,但是实际上 CSS 像素确是一个抽象的单位,具体含有多少个设备像素不是一定的。
像素比(DPR)
计算公式为:DPR = 设备像素 / CSS 像素。
举个例子,如果 CSS 像素和设备像素 1:1 关系,那么 DPR 值就为 1。如果 1 个 CSS 像素对应 2 个设备像素,那么 DPR 值就为 2。
说简单点,就是一个 CSS 像素要用多少个设备像素来显示。如果 DPR 值为 1,表示用一个设备像素就够了,如果 DPR 值为 2,则表示一个 CSS 像素要用 2 个设备像素来表示。
可以通过 window.devicePixelRatio 获取一个设备的 DPR。
viewPort 视口 2024-02-11
视口,英语全称 viewport,指的是设备的屏幕上能用来显示我们的网页的那一块区域,再具体一点,就是浏览器上(也可能是一个 app 中的 webview)用来显示网页的那部分区域。
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.container{
width: 375px;
display: flex;
}
.container>div{
width: 50%;
height: 50px;
}
.container>div:nth-child(1) {
background-color: red;
}
.container>div:nth-child(2) {
background-color: yellow;
}
</style>
</head>
<body>
<div class="container">
<div></div>
<div></div>
</div>
</body>
在上面的代码中,我们将默认的视口设置取消了,此时就会采用默认的 980px,而我们的 div.contianer 设置的为 375px,效果如下:
可以看到,由于默认的视口宽度为 980px,因此 div.container 并没有占满,只占了一半都还不到。
我们所期待的应该按照设备的 CSS 像素来作为标准。还记得 iPhone 6/7/8 的 CSS 像素是多少么?没错,是 375 x 667,也就是说现在的网页就应该按照 375px 的标准。
视口的分类
- layout viewport
- visual viewport
- ideal viewport
把浏览器默认的 viewport,也就是前面我们所讲的 980px 宽的 viewport 叫做 layout viewport。这个 layout viewport 的宽度可以通过 window.innerWidth 来获取。
然而,layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个 viewport 来代表浏览器可视区域的大小,把这个 viewport 叫做 visual viewport。visual viewport 的宽度可以通过 document.documentElement.clientWidth 来获取。
现在我们已经有两个 viewport 了:layout viewport 和 visual viewport。layout viewport 是网页实际的宽度,而 visual viewport 是设备的宽度。
在早期 iPhone3GS 时代,由于一个 CSS 像素对应一个设备像素,因此 visual viewport 和设备 CSS 宽度是等价的。
但是从 iPhone4 时代开始,一个 CSS 像素对应 2 个设备像素,设备的 CSS 宽度仍然是 320px,但是物理像素翻了倍。
于是 ideal viewport,也就是第三个 viewport ——移动设备的完美适配 viewport,其实对应的就是设备的 CSS 宽度。
视口相关属性
移动设备默认的 viewport 是 layout viewport,也就是那个比屏幕要宽的 viewport,但在进行移动设备网站的开发时,我们需要的是 ideal viewport。那么怎么才能得到 ideal viewport 呢?
这就该轮到 meta 标签出场了。
我们在开发移动设备的网站时,最常见的的一个动作就是把下面这个东西复制到我们的 head 标签中:
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
该 meta 标签的作用是让当前 viewport 为 ideal viewport,同时不允许用户手动缩放。
也许允不允许用户缩放不同的网站有不同的要求,但让 viewport 的宽度为 ideal viewport,这个应该是大家都想要的效果,如果你不这样的设定的话,那就会使用那个比屏幕宽的默认 viewport,在不缩放的情况下会出现横向滚动条。
name 为 viewport 的标 meta 标签最早是由苹果公司在其 safari 浏览器中引入的,目的就是解决移动设备的 viewport 问题。后来安卓以及各大浏览器厂商也都纷纷效仿,引入对 meta viewport 的支持,事实也证明这个东西还是非常有用的。
在苹果的规范中,meta viewport 有 6 个属性(暂且把 content 中的那些东西称为一个个属性和值),如下:
| 属性名 | 作用 |
|---|---|
| width | 设置 layout viewport 的宽度,为一个正整数,或字符串"device-width" |
| height | 设置 layout viewport 的高度,这个属性对我们并不重要,很少使用 |
| initial-scale | 设置页面的初始缩放值,为一个数字,可以带小数 |
| minimum-scale | 允许用户的最小缩放值,为一个数字,可以带小数 |
| maximum-scale | 允许用户的最大缩放值,为一个数字,可以带小数 |
| user-scalable | 是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes 代表允许 |
这些属性可以同时使用,也可以单独使用或混合使用,多个属性同时使用时用逗号隔开就行了。
最简单的方式是设置 width=device-width,表示把默认的 layout viewport 的宽度设为移动设备的屏幕宽度。
device-width = 设备分辨率/devicePixelRatio(设备像素比)
下图是这句代码在各大移动端浏览器上的测试结果:
可见通过 width=device-width,所有浏览器都能把当前的 viewport 宽度变成 ideal viewport 的宽度。
例如:
<div class="container">
<div></div>
<div></div>
</div>
<script>
console.log("document.documentElement.clientWidth:",document.documentElement.clientWidth);
console.log("window.innerWidth:",window.innerWidth);
</script>
* {
margin: 0;
padding: 0;
}
.container{
width: 375px;
display: flex;
}
.container>div{
width: 50%;
height: 50px;
}
.container>div:nth-child(1) {
background-color: red;
}
.container>div:nth-child(2) {
background-color: yellow;
}
<meta name="viewport" content="width=device-width">
效果如下:
但要注意的是,在 iphone 和 ipad 上,无论是竖屏还是横屏,宽度都是竖屏时 ideal viewport 的宽度。
另外,如果我们只设置 initial-scale 为 1,也能达到相同的效果,也就是说能把当前的 viewport 变为 ideal viewport。
<meta name="viewport" content="initial-scale=1">
关于缩放
最后要说一下关于缩放的问题。
前面我们说过,即使使用手机浏览器打开 PC 端的网页,手机浏览器也能很智能的对页面进行缩放,从而不出现滚动条。
那么这个缩放比例究竟是多少呢?
这里其实有一个公式,那就是:
当前缩放值 = ideal viewport宽度 / layout viewport 宽度
比如说,我们不设置任何的 viewport meta 标签,此时 layout viewport 的宽度为 980px,但我们可以看到浏览器并没有出现横向滚动条,因为浏览器默认的把页面缩小了。
根据上面的公式,缩放比就为 375 / 980 = 0.38 左右。
也就是当前的 initial-scale 默认值应该是 0.38 这样子。但是如果指定了 initial-scale 的值,那么这个默认值就不起作用了。
最后总结一下,为了保证在不同设备中,显示网页的视口正常,最常见的设置如下:
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">