这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天
写在开头
青训营的课程已经告一段落了,在项目开发中也与移动端适配有关,于是打算讲讲移动端适配内容
移动端适配
为什么需要移动端适配
让拥有不同屏幕大小的终端设备拥有相适应的 UI 界面,让拥有更大屏幕的终端展示更多的内容
前置知识
像素
像素是指由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值,小方格颜色和位置就决定该图像所呈现出来的样子。
图片、电子屏幕(手机、电脑)就是由无数个具有特定颜色和特定位置的小方块拼接而成。
像素可以作为图片或电子屏幕的最小组成单位。
分辨率
分辨率指含有的像素数。
iPhone XS Max 的分辨率分别为 2688 x 1242。这表示手机分别在垂直和水平上所具有的像素点数。
一张图片的分辨率为 800 x 400。这表示图片分别在垂直和水平上所具有的像素点数为 800 和 400。
viewport(重点)
viewport 即视窗、视口,用于显示网页部分的区域,在 PC 端视口即是浏览器窗口区域,在移动端,为了让页面展示更多的内容,视窗的宽度默认不为设备的宽度,在移动端视窗有三个概念:布局视窗、视觉视窗、理想视窗
布局视窗
在浏览器窗口css的布局区域,布局视口的宽度限制css布局的宽。为了能在移动设备上正常显示那些为pc端浏览器设计的网站,根据设备不同,布局视口的默认宽度有可能是768px、980px或1024px……等,一般都比移动端浏览器可视区域大很多,所以就会出现浏览器出现横向滚动条的情况。
当我们以百分比来指定一个元素的大小时,它的计算值是由这个元素父级计算而来的。当这个元素是最顶级的元素时,它就是基于布局视口来计算的。
我们可以通过调用document.documentElement.clientWidth / clientHeight来获取布局视口大小
视觉视窗
终端设备显示网页的区域,即我们能看得到的部分
注意: 当我们在手机中缩放网页的时候,操作的是视觉视口,而布局视口仍然保存原来的宽度。
理想视窗
针对当前设备最理想的展示页面的视窗,可以使网页在移动端浏览器上获得最理想的浏览和阅读的宽度,不会出现横向滚动条,页面刚好全部展现在视窗内,理想视窗也就是终端屏幕的宽度。
在实际开发中,为了实现理想视口,需要给移动端页面添加meta标签配置视口,通知浏览器进行处理。
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
Value | 可能值 | 描述 |
|---|---|---|
width | 正整数或device-width | 以pixels(像素)为单位, 定义布局视口的宽度。 |
initial-scale | 0.0 - 10.0 | 定义页面初始缩放比率。 |
minimum-scale | 0.0 - 10.0 | 定义缩放的最小值;必须小于或等于maximum-scale的值。 |
maximum-scale | 0.0 - 10.0 | 定义缩放的最大值;必须大于或等于minimum-scale的值。 |
user-scalable | yes / no | 如果设置为 no,用户将不能放大或缩小网页。默认值为 yes。 |
为了在移动端让页面获得更好的显示效果,我们必须让布局视口、视觉视口都尽可能等于理想视口。
device-width就等于理想视口的宽度,所以设置width=device-width就相当于让布局视口等于理想视口。
像素
设备像素(物理像素)
设备像素(device pixels)也叫物理像素,指的是显示器上的真实像素,每个像素的大小是屏幕固有的属性,屏幕出厂以后就不会再改变。
设备分辨率描述的就是这个显示器的宽和高分别是多少个设备像素,例如常见的显示器的分辨率为 1920 * 1080。
设备像素和设备分辨率是由操作系统来管理的,浏览器不知道、也不必知道设备分辨率的大小,它主要根据逻辑分别率来计算的。
设备独立像素(逻辑像素)
用设备独立像素定义的尺寸,不管屏幕的参数如何,都能以合适的大小显示(这也是设备独立像素名字的由来)。操作系统是如何做到的呢?对于那些像素密度高的屏幕,将多个设备像素划分为一个逻辑像素。至于将多少设备像素划分为一个逻辑像素,这由操作系统决定。
举个例子
原先在 1280×720 设备分辨率的显示屏中,显示高度为 12 个设备像素的字体,现在放到设备分辨率为 2560 ×1440 的显示屏中,如果要想得到原先的大小,则需要 24 个设备像素
设备像素比(DPR)
设备独立像素可以简单认为是计算机坐标系统中的一个点,而物理像素可以简单认为是显示器硬件中的一个点。那么它们之间的关系是怎样的呢?设备像素比就是表示二者之间关系的一个概念。
设备像素比就是指设备物理像素和设备独立像素之间的比值。在 JS 中可以通过 window.devicePixelRatio 获取。可以简单理解为:硬件中一个点的大小和系统中一个点的大小的比值。对于某一个固定的设备,这个值是固定不变的。
倍图
在实际开发中,我们大多数情况下会使用到2倍图和3倍图来操作background-size属性,来解决精灵图(雪碧图)或背景图片模糊的问题。
在实际开发中,我们从视觉那拿到的设计图通常都是640px或750px的设计图,所以为了解决设备中背景图模糊的问题,我们可以把更多的像素点压缩至一块屏幕,或者说压缩到一个逻辑像素(css像素)内,从而达到更高的分辨率并提高屏幕显示的细腻程度。
背景缩放 background-size
介绍:background-size属性指定背景图片的大小
语法:background-size: length | percentage | cover | contain;
单位:px(像素) 或 %(百分比)
注意:如果想要图片在盒子内全部覆盖显示,则使用100%即可
| 值 | 描述 |
|---|---|
| length | 设置背景图片高度和宽度。第一个值设置宽度,第二个值设置的高度。 如果只给出一个值,第二个是设置为 auto(自动) |
| percentage | 将计算相对于背景定位区域的百分比。第一个值设置宽度,第二个值设置的高度。如果只给出一个值,第二个是设置为"auto(自动)" |
| cover | 此时会保持图像的纵横比并将图像缩放成将完全覆盖背景定位区域的最小大小。 |
| contain | 此时会保持图像的纵横比并将图像缩放成将适合背景定位区域的最大大小。 |
适配方案
媒体查询
基于 css 的媒体查询属性 @media 分别为不同屏幕尺寸的移动设备编写不同尺寸的 css 属性,示例如下所示。虽然此方法能在一定程度上解决移动设备适配的问题,但我们也可以看出其存在以下问题。
- 页面上所有的元素都得在不同的 @media 中定义一遍不同的尺寸,这个代价有点高;
-
如果再多一种屏幕尺寸,就得多写一个 @media 查询块;
@media screen and (min-width: 375px) {
.logo {
width : 62.5px;
}
}
@media screen and (min-width: 360px) {
.logo {
width : 60px;
}
}
@media screen and (min-width: 320px) {
.logo {
width : 53.3333px;
}
}
rem 单位
rem(font size of the root element)是指相对于根元素的字体大小的单位,如果我们设置 html 的 font-size 为 16px,则如果需要设置元素字体大小为 16px,则写为 1rem。但是其还是必须得借助 @media 属性来为不同大小的设备设置不同的 font-size,相对上一种方案,可以减少重复编写相同属性的代价,简单示例如下所示。
@media only screen and (min-width: 320px) {
html {
font-size : 320px;
}
}
@media only screen and (min-width: 360px) {
html {
font-size : 360px;
}
}
@media only screen and (min-width: 375px) {
html {
font-size : 375px;
}
}
.logo{
width : 180rem;
}
flexible
在 rem 方案上进行改进,我们可以使用 js 动态来设置根字体,这种方案的典型代表就是 flexible 适配方案。
其实 flexible 方案是在 模拟 viewport 功能,只是随着浏览器的发展及兼容性增强,viewport 已经能兼容绝大部分主流浏览器,并且 flexible 方案自身存在的问题,所有其也已几乎退出历史潮流。
引用 lib-flexible 的 github 主页的原话:
由于 viewport 单位得到众多浏览器的兼容,lib-flexible 这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用 viewport 来替代此方案。
viewport
由于 viewport 单位得到众多浏览器的兼容,所以目前基于 viewport 的移动端适配方案被各大厂团队所采用。
vw 作为布局单位,从底层根本上解决了不同尺寸屏幕的适配问题,因为每个屏幕的百分比是固定的、可预测、可控制的。 viewport 相关概念如下:
- vw:是 viewport's width 的简写,1vw 等于 window.innerWidth 的 1%;
- vh:和 vw 类似,是 viewport's height 的简写,1vh 等于 window.innerHeihgt 的 1%;
- vmin:vmin 的值是当前 vw 和 vh 中较小的值;
-
vmax:vmax 的值是当前 vw 和 vh 中较大的值;
假设我们拿到的视觉稿宽度为 750px,视觉稿中某个字体大小为 75px,则我们的 css 属性只要如下这么写,不需要额外的去用 js 进行设置,也不需要去缩放屏幕等;
.logo {
font-size: 10vw; // 1vw = 750px * 1% = 7.5px
}
在 html 头部设置 mata 标签如下所示,让当前 viewport 的宽度等于设备的宽度,同时不允许用户手动缩放。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
总结一下
-
编写 标签设置 viewport 的内容 width=device-width,让网页宽度等于视窗宽度
-
在 css 中使用 px
-
在适当的场景使用flex布局,或者配合vw进行自适应
-
在跨设备类型的时候(pc <-> 手机 <-> 平板)使用媒体查询
-
在跨设备类型如果交互差异太大的情况,考虑分开项目开发
写在结尾
这些大概就是关于移动端适配的一些知识点,任重而道远,加油!