前端开发之移动端自适应布局

时间:2024-01-22 15:11:40

大家在做移动端开发的时候如果只用px+百分比的布局方式而不做任何自适应处理的话就会出现这种情况:按照750px设计图写页面,如果设计图给的字体大小是28px一般情况下会除以2(这一步已经错了),写完以后放到iphone6s和iphone5测试就会发现本来在6s上感觉蛮好的到了5上就变大了。然后心中万马奔腾……

现在,给大家分享两种常用的解决方案

  • 1、通过动态设置 viewport的 width 和 initial-scale

  • 2、通过动态设置跟元素Html的font-size 即 rem解决方案

1、meta viewport

meta标签大家都很熟悉了,首先来看一下meta viewport 的6个属性:

属性名解释
width 设置viewport 的宽度,为一个正整数,或字符串"width-device"
initial-scale 设置页面的初始缩放值,为一个数字,可以带小数
minimum-scale 允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale 允许用户的最大缩放值,为一个数字,可以带小数
height 设置viewport 的高度,这个属性并不重要,很少使用
user-scalable 是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许

一般情况下width的值设置为width-device即可,即当前设备的屏幕宽度,我们可以通过window.screen.width获取。所以要想在不同手机上自适应,我们就要动态的改变initial-scale(初始缩放值),并且设置user-scalable=no禁止用户手动缩放页面。

举一个例子:如果设计师给的尺寸是750px的,如何把750px的设计图等比缩放到我们当前宽度的手机上呢?假如当前手机的屏幕宽度是恰好是750px,那initial-scale就等于1好了完全不用缩放。假如当前的手机宽度是375px(iphone6/7/8),那岂不是要缩放一倍了(initial-scale=0.5),对的,缩放的倍数就等于当前手机屏幕宽度除以设计图的宽度。如果设计师给的是640px宽的图,针对不同的手机initial-scale的值是多少呢?(答案就在上一句)。

所以initial-scale的值是要动态获取的然后将meta标签添加到header标签里面,这就要用js操作dom了(js基础知识)。见下代码示例:

<script>
    var _vwidth = window.screen.width;
    var _scale = _vwidth / 750;
    var _meta = document.createElement(\'meta\');
    _meta.setAttribute(\'name\', \'viewport\');
    _meta.setAttribute(\'content\', \' width = device - width , user - scalable = no , initial - scale = \' + _scale);
    document.getElementsByTagName(\'head\')[0].appendChild(_meta);
</script>

 

之后就可以根据设计图给的尺寸大小写css了,是28px我们就写28像素,宽度是750px我们就写750px(当然:也可以写100%)。

2、rem布局

rem是指相对于根元素的字体大小的单位,它就是一个相对单位。看到rem大家一定会想起em单位,em是指相对于父元素的字体大小的单位。一个计算的规则是依赖根元素一个是依赖父元素计算。rem自适应原理就是动态改变根元素html的font-size大小。如果设置了html{font-size:20px;},那么1rem=20px。如何动态改变html的fontSize呢,有两种方式可以实现。第一种是通过css3的媒体查询,这样的话在做开发前就要先统计有哪些主流的屏幕设备,然后去针对这些设备去做不同的兼容,如下示例:

html {
    font - size:

        20px;
}

@media only screen and (min - width: 375px) {
    html {
        font - size:

            25px ! important;

    }
}

@media only screen and (min - width: 428px) {
    html {
        font - size:

            26.75px ! important;

    }
}

@media only screen and (min - width: 481px) {
    html {
        font - size:

            30px ! important;


    }
}

@media only screen and (min - width: 569px) {
    html {
        font - size:

            35px ! important;


    }
}

@media only screen and (min - width: 641px) {
    html {
        font - size:

            40px ! important;


    }
}

 

到这里肯定有很多人会疑问是怎么计算出不同分辨率下font-size的值的?其实这只是一个参考,如果设计图尺寸是750,你可以将750对应的fontSize设置为100px,375对应fontSize就是50px以此类推。之所以在媒体查询上面设置一个font-size : 20px;是因为当设备宽度小于375的时候都采用1rem=20px,当然这个值可以更改的。如下示例:

html {
    font - size:

        20px;
}

@media only screen and (min - width: 750px) {
    html {
        font - size:

            100px ! important;


    }
}

@media only screen and (min - width: 375px) {
    html {
        font - size:

            50px ! important;


    }
}

 

用css的方法是不能做全适配的,因为可能我们没有统计全或者未来还会出现更多不同分辨率的手机,但是用JS是可以实现全适配。以下是通过js实现自适应,此时是针对750像素设计图1rem=100px,即设计图中字体大小为28像素时,我们要设置为0.28rem。还是很好换算的。如果设计图给的是640px,只需要将结尾处的参数改成640,640即可。

(function(designWidth, maxWidth) {
    var doc = document,
        win = window,
        docEl = doc.documentElement,
        remStyle = document.createElement("style"),
        tid;

    function refreshRem() {
        var width = docEl.getBoundingClientRect().width;
        maxWidth = maxWidth || 540;
        width > maxWidth && (width = maxWidth);
        var rem = width * 100 / designWidth;
        remStyle.innerHTML = "html{font-size:" + rem + "px;}"
    }
    if (docEl.firstElementChild) {
        docEl.firstElementChild.appendChild(remStyle)
    } else {
        var wrap = doc.createElement("div");
        wrap.appendChild(remStyle);
        doc.write(wrap.innerHTML);
        wrap = null
    }
    refreshRem();
    win.addEventListener("resize", function() {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300)
    }, false);
    win.addEventListener("pageshow", function(e) {
        if (e.persisted) {
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300)
        }
    }, false);
    if (doc.readyState === "complete") {
        doc.body.style.fontSize = "16px"
    } else {
        doc.addEventListener("DOMContentLoaded", function(e) {
            doc.body.style.fontSize = "16px"
        }, false)
    }
})(750, 750);

 

在项目中大家可根据实际情况选择,祝大家开发顺利少加班!!!

 

欢迎扫描下方二维码关注,这里更多前端技术分享,让我们一起成长 -- web前端周刊