如何做移动端适配
# 1. viewport 缩放
在写HTML、CSS对设计稿进行还原时不关注屏幕尺寸的差异,而是直接按设计稿的标注来开发。比如设计稿里标注的文字字号是30px,CSS里就设置文字字号30px。
页面开发好后,在HTML的head标签里加入如下代码:
<meta name="viewport" content="width={设计稿宽度}, initial-scale={屏幕逻辑像素宽度/设计稿宽度}" >
举个例子。假设设计师交付的设计稿宽度是750px,设计稿上一个标题字号标注的是32px 、margin是20px。我们以标注的大小来写CSS。之后需要通过JavaScript计算获取屏幕的宽度(假设需要适配逻辑像素宽度是428px的屏幕),在HTML的head里添加以下代码 可(428/759 = 0.57)。
<meta name="viewport" content="width=750px, initial-scale=0.57" >
这段代码的意思是:设置布局视口(layout viewport)的宽度为750px(此时页面一般会超出屏幕),再缩放页面(initial-scale)使其恰好撑满屏幕。
关于viewport的设置:
# 2. 动态rem方案
首先,rem是一种相对单位,它相对于根标签html的字体大小font-size,比如html标签的font-size为16px,那么1rem就相当于是16px。
根据这个原理,可以通过动态设置html标签的font-size大小,来实现不同视口大小的移动端设备等比例缩放页面。(这个方法其实就是模拟vw,1vw就是视图窗口宽度的1%,这个具体的会在下面说。)
举个例子,我们可以通过如下代码动态设置html标签的font-size大小:
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit();
2
3
4
5
6
这相当于设置了,1rem = 10%的视口大小。假设我们的设计稿给的是750px宽度的,那么其中一个宽度为375px的容器,换算成rem后就是 375*10/750 = 5rem。这样不管在什么样的设备中,这个容器都是占据50%的宽度。
当然这样每次计算是比较麻烦的,我们可以借助px2rem插件自动计算这个rem值。在不使用插件的情况下也可以简化计算的方式:
const WIDTH = 750 //如果是尺寸的设计稿在这里修改
const setView = () => {
//设置html标签的fontSize
document.documentElement.style.fontSize = (100*screen.width/WIDTH) + 'px'
}
window.onorientationchange = setView
2
3
4
5
6
在明确设计稿的宽度为750px的情况下,相当于先将移动设备视口分为750份,这时候1rem就是1/750的宽度,如果有一个宽度为375px的容器,那么就应该设为375rem,但是这比例太小了,我们一般会乘上一个倍数,一般是100,这样我们可以直接给这个容器设置为3.75rem,当然50也是可以的,那就应该设置为7.5rem,明显没有100好算。。。
# 3. vw、vh方案
vh、vw方案即将视觉视口宽度 window.innerWidth 和视觉视口高度 window.innerHeight 等分为 100 份。 上面的flexible方案就是模仿这种方案,因为早些时候vw还没有得到很好的兼容。
- vw(Viewport's width):1vw等于视觉视口的1%
- vh(Viewport's height) : 1vh 为视觉视口高度的1%
- vmin : vw 和 vh 中的较小值
- vmax : 选取 vw 和 vh 中的较大值
vh和vw方案和rem类似也是相当麻烦需要做单位转化,而且px转换成vw不一定能完全整除,因此有一定的像素差。 不过在工程化的今天,webpack解析css 的时候用postcss-loader 有个postcss-px-to-viewport能自动实现px到vw的转化:
{
loader: 'postcss-loader',
options: {
plugins: ()=>[
require('autoprefixer')({
browsers: ['last 5 versions']
}),
require('postcss-px-to-viewport')({
viewportWidth: 375, //视口宽度(数字)
viewportHeight: 1334, //视口高度(数字)
unitPrecision: 3, //设置的保留小数位数(数字)
viewportUnit: 'vw', //设置要转换的单位(字符串)
selectorBlackList: ['.ignore', '.hairlines'], //不需要进行转换的类名(数组)
minPixelValue: 1, //设置要替换的最小像素值(数字)
mediaQuery: false //允许在媒体查询中转换px(true/false)
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 参考文章链接
聊一聊移动端适配思路 (opens new window)
关于移动端适配,你必须要知道的 (opens new window)
面试官:你了解过移动端适配吗? (opens new window)