移动端适配方案

4,812 阅读4分钟

为什么需要移动端适配?

现如今,web页面已经不局限于在PC端运行,也需要在移动端运行。而移动端的机型是非常多的,所以我们常常需要将页面做一个移动端适配,使其能在不同的终端完美运行。

适配方案

1. rem适配

原理

rem是css3新增的一个相对单位,当使用rem为元素设定字体大小时,相对的是HTML根元素的字体大小。例如你给html设置font-size为16px,html中的div元素设置font-size为1rem,则这1rem也是16px。

rem适配的原理是布局等比例缩放,我们可以动态控制html中font-size的大小来改变rem的大小。

实现方法

1. 设置视口viewport

在移动端配置视口的方法是设置一个meta标签:

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">

其中,width为定义视口的宽度,height为定义视口的高度,initial-scale为定义初始缩放值,maximum-scale和minimum-scale分别为定义放大最大和缩小最小比例,user-scalable指是否允许用户手动缩放页面。上面的meta标签例子是将scale设置为固定1倍视口的大小。

如果我们不去设置,则浏览器的默认设置为:viewport=980,initial-scale为空

让我们看看设置与不设置viewport的区别:

不设置:

不设置viewport

设置:

设置viewport

同样设置宽高为300px的正方形,可以看出,当设置viewport时,会有一个缩放效果。

我们也可以根据设备像素比例devicePixelRatio的值来缩放viewport,代码如下:

let viewport = document.querySelector('meta[name=viewport]')
let dpr = window.devicePixelRatio || 1
let scale = 1 / dpr
viewport.setAttribute(
    "content",
    "width=device-width" +
    ",initial-scale=" +
    scale +
    ", maximum-scale=" +
    scale +
    ", minimum-scale=" +
    scale +
    ", user-scalable=no"
)

这样我们就可以实现元素在不同设备下有不同的缩放效果

缺点:边框等不需要缩放的元素,也会跟着缩放

注意

  1. viewport标签只对移动端浏览器有效,对PC端浏览器是无效的。
  2. 当缩放比例为100%时,逻辑像素 = CSS 像素宽度 = 理想视口的宽度 = 布局视口的宽度。
  3. 单独设置initial-scale或 width都会有兼容性问题,所以设置布局视口为理想视口的最佳方法是同时设置这两个属性。
  4. 即使设置了user-scalable = no,在Android Chrome浏览器中也可以强制启用手动缩放。
2. 动态设置rem

通过js获取设备宽度来动态设置font-size随着视口大小的改变而改变,流程如下:

  1. 获得设计稿尺寸,如750px
  2. 对设计稿标注进行转换
  3. 需要等比缩放的使用rem,不需要缩放的,例如border阴影,则使用px
  • 代码如下:
const WIDTH = 750//设计稿宽度
function setRemUnit() {
  let rem = 100*screen.width/WIDTH
  document.documentElement.style.fontSize = `${rem}px`
}
setRemUnit()

看看无设置和有设置的区别:

除了字体,设置宽高等值,都可以达到缩放的效果。

缺点

  1. css与js代码具有一定的耦合性
  2. 必须将改变font-size的代码放在css样式之前

2. vw适配

如果说我们要一个不需要JS和CSS耦合在一起的单位,那vw/vh就是一个不错的选择。

vw:view width,指视口宽度的百分比,如:1vw = 视口宽度的1%

vh:view height,指视口高度的百分比,如:1vh = 视口高度的1%

vmin:vmin的值是当前vw和vh中较小的值

vmax:vmax的值是当前vw和vh中较大的值

使用起来也比较简单,比如我假设设计稿使用1080px宽度,则100vw = 1080px,即1vw = 10.8px。我们可以根据设计图上的px值直接转换成对应的vw值,也可以使用PostCSS的插件postcss-px-to-viewport,可以直接在代码中写px。

例子:设置一个视口宽高都占百分之五十的div

.box {
  width: 50vw;
  height: 50vh;
  background-color: red;
}

3. rem配合vw

我们也可以通过vw来动态调整html的font-size,元素布局上使用rem单位,并使用媒体查询@media,当超过一定宽度时设置font-size为px限制根元素字体的大小。

@media screen and (max-width: 320px) {
      html {
          font-size: 64px;
      }
}
@media screen and (min-width: 540px) {
        html {
            font-size: 108px;
        }
 }
html {
  font-size: 20vw;
}
.box {
    max-width: 540px;
    min-width: 320px;
}

总结

  • 新闻、社区等可阅读内容比较多的场景:px+flex+百分比

  • 视觉图形组件较多的,或者是组件位置有一定相对依赖关系的场景:vw + rem