0%

移动端适配

前置知识

屏幕尺寸:以屏幕对角线的长度计算,单位是英寸

像素 pixel:显示屏画面上表示出来的最小单位

屏幕分辨率:一个屏幕具体由多少个像素点组成,单位是px

物理像素:在同一个设备上,他的物理像素是固定的,也就是厂家在生产显示设备时就决定的实际点的个数,对于不同设备物理像素点的大小是不一样的

逻辑像素(设备独立像素):(与设备无关的逻辑像素,代表可以通过程序控制使用的虚拟像素)

设备像素比dpr:计算公式为:DPR = 物理像素/逻辑像素

当设备像素比为1:1时,使用1(1×1)个设备像素显示1个CSS像素;

当设备像素比为2:1时,使用4(2×2)个设备像素显示1个CSS像素;

当设备像素比为3:1时,使用9(3×3)个设备像素显示1个CSS像素。

视口viewport:

viewport指的是视口,它是浏览器或者app中webview显示页面的区域,一般,PC端的视口指的是浏览器窗口区域,而移动端有三个视口:

layout viewport:布局视口

visual viewport:视觉视口

ideal viewport:理想视口

布局视口(layout viewport):

由浏览器提出的一种虚拟的布局视口,用来解决页面在收上显示的问题,这种视口可以通过标签设置viewport来改变,移动设备上的浏览器会把自己默认的viewport设为980px或者1024px,也可能是其它值,这个是由设备自己决定的),但带来的后果就是浏览器会出现横向滚动条,因为浏览器可视区域的宽度是比这个默认的viewport的宽度要小的。

我们可以通过document.documentElement.clientWidth来获取布局视口大小

视觉视口(visual viewport)

它指的是浏览器的可视区域,也就是我们在移动端设备上能够看到的区域。默认与当前浏览器窗口大小相等,当用户对浏览器进行缩放时,不会改变布局视口的大小,但会改变视觉窗口的大小。

meta viewport

对于移动端页面,可以采用<meta>标签来配置视口大小和缩放等。

1
2
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
复制代码
  • width:该属性被用来控制视窗的宽度,可以将width设置为320这样确切的像素数,也可以设为device-width这样的关键字,表示设备的实际宽度,一般为了自适应布局,普遍的做法是将width设置为device-width
  • height:该属性被用来控制视窗的高度,可以将height设置为640这样确切的像素数,也可以设为device-height这样的关键字,表示设备的实际高度,一般不会设置视窗的高度,这样内容超出的话采用滚动方式浏览。
  • initial-scale:该属性用于指定页面的初始缩放比例,可以配置0.0~10的数字,initial-scale=1表示不进行缩放,视窗刚好等于理想视窗,当大于1时表示将视窗进行放大,小于1时表示缩小。这里只表示初始视窗缩放值,用户也可以自己进行缩放,例如双指拖动手势缩放或者双击手势放大。安卓设备上的initial-scale默认值: 无默认值,一定要设置,这个属性才会起作用。在iphone和ipad上,无论你给viewport设的宽的是多少,如果没有指定默认的缩放值,则iphone和ipad会自动计算这个缩放值,以达到当前页面不会出现横向滚动条(或者说viewport的宽度就是屏幕的宽度)的目的。
  • maximum-scale:该属性表示用户能够手动放大的最大比例,可以配置0.0~10的数字。
  • minimum-scale:该属性类似maximum-scale,用来指定页面缩小的最小比例。通常情况下,不会定义该属性的值,页面太小将难以浏览。
  • user-scalable:该属性表示是否允许用户手动进行缩放,可配置no或者yes。当配置成no时,用户将不能通过手势操作的方式对页面进行缩放。

这里需要注意的是viewport只对移动端浏览器有效,对PC端浏览器是无效的。

rem适配:

是CSS3新增的一个相对单位,是指相对于根元素的字体大小的单位。

  • 将屏幕宽度分为10份,设置html的font-size为window.innerWidth/10px
  • 1rem=window.innerWidth/10px
  • 根据UI的px计算相应rem:比如盒子宽320px,(320px/window.innerWidth)*10=5.333rem
  • 将rem转为不同的px尺寸在不同手机上呈现:5.333rem*window.innerWidth/10px
1
2
3
4
5
//给html标签添加font-size
document.addEventListener('DOMContentLoaded', function(e) {
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
}, false);

使用Sass定义一个ps2rem函数

1
2
3
4
5
6
7
@funtion px2rem($px){
$rem: 75px;//750/10
@return ($px/$rem)+rem
}
.box1 {
width: px2rem(320px);//(320/750)*10=4.266rem
}

vw,vh适配:

vw(Viewport Width)vh(Viewport Height)是基于视图窗口的单位,是css3中提出来的,基于视图窗口的单位。

vh、vw方案即将视觉视口宽度 window.innerWidth和视觉视口高度 window.innerHeight 等分为 100 份。

上面的flexible方案就是模仿这种方案,因为早些时候vw还没有得到很好的兼容。

  • vw(Viewport's width)1vw等于视觉视口的1%
  • vh(Viewport's height) :1vh 为视觉视口高度的1%
  • vmin : vwvh 中的较小值
  • vmax : 选取 vwvh 中的较大值

如果按视觉视口为375px,那么1vw = 3.75px,这时UI给定一个元素的宽为75px(设备独立像素),我们只需要将它设置为75 / 3.75 = 20vw

1
2
@device-width: 375
@vw: (100vw/device-width)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<template>
<div class="songyao">
<h1>{{ username }}</h1>
<p>
了解脚手架及脚手架指令请移步个人博客<br>
check out the
<a href="http://47.100.126.169/zmengBlog" target="_blank" rel="noopener">逐梦博客</a>.
</p>
<p>微信公众号:<span class="wx_name">前端南玖</span></p>
</div>
</template>

<script>
export default {
name: 'songyao',
data() {
return {
username: 'songyao-cli(vue 模板)'
}
},
}
</script>

<style lang="less">
.songyao{
h1{

font-size: 24*@vw;
}
p{

font-size: 16*@vw;
}
.wx_name{
color:brown;
}
}

</style>

viewport和px

这种方案可以让我们在开发时不用关注设备屏幕尺寸的差异,直接按照设计稿上的标注进行开发,也无需单位的换算,直接用px。HTML 的 head 标签里加入 <meta name="viewport" content="width={设计稿宽度}, initial-scale={屏幕逻辑像素宽度/设计稿宽度}" >

假如UI给我们提供的设计稿宽度时375px,我们则需要将页面的viewport的width设为375,然后再根据设备的逻辑像素将页面进行整体放缩。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export function initViewport() {
const width = 375; // 设计稿宽度
const scale = window.innerWidth / width
// console.log('scale', scale)
let meta = document.querySelector('meta[name=viewport]')
let content = `width=${width}, init-scale=${scale}, user-scalable=no`
if(!meta) {
meta = document.createElement('meta')
meta.setAttribute('name', 'viewport')
document.head.appendChild(meta)
}
meta.setAttribute('content', content)
}


总结:

rem:

  • 适配原理复杂
  • 需要使用js
  • 设计稿标注px换算到css的rem计算简单
  • 方案灵活,即能实现整体缩放,又能实现局部不缩放

vw:

  • 适配原理简单
  • 不需要使用js
  • 设计稿标注的px换算为css的vw计算复杂

viewport+px:

  • 适配原理简单
  • 需要使用js
  • 直接使用设计稿标注无需换算
  • 方案死板,只能实现页面级别肢体缩放

参考:https://juejin.cn/post/7085931616136069156#heading-19

https://juejin.cn/post/6844903590968950797#heading-7