移动端适配
# 链接一篇移动端适配的文章
https://juejin.cn/post/6844903845617729549
# 移动端开发简介
移动端开发目前主要包括三类
- 原生App开发(iOS、Android、RN、uniapp、Flutter等)
- 小程序开发(原生小程序、uniapp、Taro等)
- Web页面(移动端的Web页面,可以使用浏览器或者webview浏览)
移动端适配产生了两个概念
- 自适应:根据不同的设备屏幕大小来自动调整尺寸、大小;
- 响应式:会随着屏幕的实时变动而自动调整,是一种自适应;
# 视口(viewport)
视口指的是在一个浏览器中,我们可以看到的区域就是视口(viewport),fixed定位就是相对于视口的定位;在PC端的页面中,不需要对视口进行区分,因为我们的布局视口和视觉视口是同一个。
但是在移动端布局的视口和可见的视口是不太一样的。因为移动端的网页窗口往往比较小,我们可能会希望一个大的网页在移动端可以完整的显示,所以在默认情况下,移动端的布局视口是大于视觉视口的。
在移动端视口可以分为三种情况
- 布局视口(layout viewport)
- 视觉视口(visual layout)
- 理想视口(ideal layout)
# 布局视口和视觉视口
# 布局视口
默认情况下,一个在PC端的网页在移动端的显示方式
- 会按照宽度为980px来布局一个页面的盒子和内容;
- 为了显示可以完整的显示在页面中,对整个页面进行缩小;
相对于980px布局的这个视口,称之为布局视口(layout viewport);即布局视口的默认宽度是980px;
# 视觉视口
如果默认情况下,我们按照980px显示内容,那么右侧有一部分区域就会无法显示,所以手机端浏览器会默认对页面进行缩放以显示到用户的可见区域中;那么显示在可见区域的这个视口,就是视觉视口(visual viewport)
# 理想视口
如果所有的网页都按照980px在移动端布局,那么最终页面都会被缩放显示。事实上这种方式是不利于我们进行移动的开发的,我们希望的是设置100px,那么显示的就是100px。这种时候就需要设置理想视口(ideal viewport);
# 理想视口
- 默认情况下的layout viewport并不适合我们进行布局;
- 可以对layout viewport进行宽度和缩放的设置,以满足正常在一个移动端窗口的布局;
- 这个时候可以设置meta中的viewport;
<!-- 设置布局视口的宽度为设备的宽度,设备宽度与viewport大小的缩放比为1, user-scalable设置为no禁止用户缩放,如果不生效设置 minimum-scale=1.0, maximum-scale=1.0来禁止用户缩放-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,
minimum-scale=1.0, maximum-scale=1.0">
2
3
# 移动端适配方案
移动端的屏幕尺寸通常是非常繁多的,很多时候我们希望在不同的屏幕尺寸上显示不同的大小;比如我们设置一个100x100的盒子。在375px的屏幕上显示是100x100; 在320px的屏幕上显示是90+x90+; 在414px的屏幕上显示是100+x100+;其他尺寸也是类似,比如padding、margin、border、left,甚至是font-size等等。
这个时候,我们可能可以想到一些方案来处理尺寸:
- 百分比设置
- 因为不同属性的百分比值,相对的可能是不同参照物,所以百分比往往很难统一;
- 所以百分比在移动端适配中使用是非常少的;
- rem单位+动态html的font-size;
- vw单位;
- flex的弹性布局;
# 适配方案一 rem+动态html的font-size
rem单位是相对于html元素的font-size来设置的,那么如果我们需要在不同的屏幕下有不同的尺寸,可以动态的修改html的font-size尺寸。
比如如下案例:
- 设置一个盒子的宽度是2rem;
- 设置不同的屏幕上html的font-size不同;
这样在开发中,我们只需要考虑两个问题:
- 针对不同的屏幕,设置html不同的font-size;
- 将原来要设置的尺寸,转化成rem单位;
# rem的font-size尺寸
# 方案一 媒体查询
可以通过媒体查询来设置不同尺寸范围内的屏幕html的font-size尺寸;
缺点
- 需要针对不同的屏幕编写大量的媒体查询
- 如果动态改变尺寸,不会实时的进行更新
# 方案二 编写JS代码
如果希望实时改变屏幕尺寸时,font-size也可以实时更改,可以通过js代码实现
方法
- 根据html的宽度计算出font-size的大小,并且设置到html上
- 监听页面的实时改变,并且重新设置font-size的大小到html上
// 获取html元素
const htmlEl = document.documentElement;
// 设置rem基本值
function setRemUnit() {
const htmlWidth = htmlEl.clientWidth;
const htmlFontSize = htmlWidth / 100;
htmlEl.style.fontSize = htmlFontSize + "px";
}
// 第一次进入时调用
setRemUnit();
// 实时监听
window.addEventListener("resize", setRemUnit);
2
3
4
5
6
7
8
9
10
11
12
# 方案三 lib-flexible库
事实上,lib-flexible库做的事情是相同的,可以直接引入使用
# rem的单位换算
# 方案一 手动换算
比如在一个375px的屏幕上,100px宽度和高度的盒子,需要将100px转成对应的rem值,100/37.5=2.6667就是对应的计算方式。
# 方案二 less/scss函数
.pxToRem(@px){
result: (@px/@htmlFontSize) * 1rem;
}
.box{
width: .pxToRem(100)[result];
font-size: .pxToRem(18)[result]
}
2
3
4
5
6
7
# 方案三 postcss-pxtorem
在目前的前端工程化开发中,可以借助于webpack工具来完成自动转化
# 方案四 vscode插件
px to rem 插件
# vw适配方案
vw,vh是viewport的两个单位,目前已经得到众多浏览器的支持
# vw和rem的对比
rem实际上是一种过渡方案,他利用的也是vw的思想;不管是自己编写的js代码还是flexible的源码,都是将1rem等同于设计稿的1/10,再利用1rem计算相对于整个屏幕的尺寸大小;1vw刚好等于屏幕的1/100,相对于rem更加有优势
# vw相比较于rem的优势
- 不需要计算html的font-size大小,也不需要给html设置这样的一个font-size
- 不会因为设置html中font-size的大小而必须给body再设置一个font-size,防止继承
- 因为不依赖font-size的尺寸,所以不用担心某些原因html的font-size尺寸被篡改,页面尺寸混乱
- vw相比于rem更加语义化,1vw刚好事1/100的viewport的大小
- 可以具备rem之前所有的优点
- vw只存在有一个问题,将尺寸换算成vw的单位即可
- 所有目前相对于rem,更推荐使用vw
# vw的单位换算
# 方案一 手动换算
比如有一个在375px屏幕上,100px宽度和高度的盒子;比如有一个在375px屏幕上,100px宽度和高度的盒子;比如有一个在375px屏幕上,100px宽度和高度的盒子;
# 方案二 less/scss函数
@vwUnit: 3.75;
.pxToVw(@px){
result: (@px / @vwUnit) * 1vw;
}
.box{
width: .pxToVw(100)[result];
height: .pxToVw(100)[result];
}
2
3
4
5
6
7
8
# 方案三 postcss-px-to-viewport-8-plugin
同rem一样,可以通过webpack工具完成自动转化
# 方案四 vscode插件
px to vw插件,编写时自动转换