解决移动端适配的3种方法(响应式布局)

1.概述

    做移动端页面的时候,经常会遇到移动端的适配这个问题,但是并没有认真分析过是如何适配各种机型的。

    适配的根本原理其实就是将设计稿按一定的比例在不同的手机上实现。

    在分析移动段适配之前首先要了解一下rem, css3的一个相对长度单位。既然是相对长度,那就有一个参照体了,rem就是相对于html元素的font-size计算值的倍数。即1rem 等于一倍的html元素的font-size值。

2.方法一:@media + rem

    @media
      媒体查询, 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的。当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。

@media screen and (min-width:350px){
    html{font-size:342%;}
}
@media screen and (min-width:360px){
    html{font-size:351.56%;}
}
@media screen and (min-width:375px){
    html{font-size:366.2%;}
}
@media screen and (min-width:384px){
    html{font-size:375%;}
}
@media screen and (min-width:390px){
    html{font-size:380.85%;}
}
@media screen and (min-width:393px){    /* 小米NOTE */
    html{font-size:383.79%;}
}
@media screen and (min-width:410px){
    html{font-size:400%;}
}
@media screen and (min-width:432px){ /* 魅族3 */
    html{font-size:421.875%;}
}
@media screen and (min-width:480px){
    html{font-size:469%;}
}
@media screen and (min-width:540px){
    html{font-size:527.34%;}
}
@media screen and (min-width:640px){
    html{font-size: 625%;}
}
@media screen and (width:720px){
    html{font-size: 703.125%;}
}

  A:html元素的font-size值又是怎么确定的呢?(例如375px的屏幕宽度)

       屏幕宽度大于375px的会按照宽度375px来适配。设计平时给我们的设计稿一般是640px宽度或者750px宽度的,上面的都是假定设计稿是640px宽来计算的,750px也是同理计算。

    1. 屏幕宽度是375,设计稿宽度是640,ratio = 375/640=0.5859375;
    2. 我们要将设计稿上元素用css单位rem写下来,那么该如何转换,1rem应该等于稿子上多少px?
        设定1rem = 100px ;可以设定其它值吗,可以,设置为100是方便我们在写css的时候好计算,小数点直接左移两位就可以了。比如,设计稿上一个宽46px按钮,这样转换成rem直接就是0.46rem。
    3. 1rem代表设计稿上100px,又该是等于设备上最后真实的多少像素呢?

      要用到前面的屏幕宽度和设计稿的宽度比 ratio,设计稿上100px代表了真实的设备100*ratio = 58.59375px。
      换句话说 css中写的1rem等于设备58.59375px。又因为1rem等于1倍的html元素的font-size,所以这里的html元素的font-size最终应该设置成58.59375px。

      为什么上述代码中用的是百分比呢?因为一般浏览器中html元素的默认字号都是16px,但是当用户放大或者缩小浏览器字号设置时,就不是16px了,所以将html的font-size设置成百分比更好,即 58.59375/16= 366.2109375%,也就是上面例子中的366.2%了。 

  B:@media + rem适配移动端还有一个不可少的条件

    要在head标签中写入一个meta标签

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1">

    作用是让layout viewport = visual viewport,用户也不可缩放页面

3.方法二:手机淘宝 flexible.js

  flexible.js也是rem适配的,它是将设备分成10份,1rem等于1/10  

var devicePixelRatio = win.devicePixelRatio;

        dpr = devicePixelRatio || 1;
        if (isIPhone) {

            // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他设备下,仍旧使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
        
       ......
       .......
        
       metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

  win.devicePixelRatio(简称dpr),即设备像素比

  上述代码当dpr(设备物理像素和设备独立像素比)为3时候,页面缩入1/3,dpr为2时,页面缩入1/2

 function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 750) {
            width = 750 * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }

  上述代码将1rem设置成了设备真实宽度的1/10,因此html根元素的fontSize也就是设备真实宽度的1/10,假如设计给的稿子是750px宽的,写scss时1rem也就应该等于75px,scss文件可以这样写:

@function px2rem($px, $base: 75) {
    @return ($px / $base) * 1rem;
}
/*
稿子上量得某按钮宽60px,高20px
*/
.btn{
    width:px2rem(60);
    height:px2rem(20);
}

4.方法三:vw,vh进行适配

  vw:viewport width(可视窗口宽度)  1vw等于1%的设备宽度(设计稿宽度)
  vh:viewport height(可视窗口高度) 1vh等于1%的设备高度(设计稿高度) 
  这样看来vw,vh其它是最方便的,但是目前兼容性不是特别好

  只有在不需要考虑兼容的时候可以用这个相对最简便的适配方案了,比如一些混合开发里,app内的浏览器如果支持vw、vh,只在app内使用的页面就可以用了

/*窗口设计稿宽200px,高220px*/
@function px2vw($px, $base: 200) {
  @return ($px/($base/100)) + vw;
}
@function px2vh($px, $base: 220) {
  @return ($px/($base/100)) + vh;
}
/*头像宽42px,高42px*/
.avantar{
    width:px2vw(42);
    heightx:px2vh(42);
}

  以上就是解决移动端适配的三种常用方案

posted @ 2020-11-09 10:34  Judicious  阅读(6725)  评论(0编辑  收藏  举报