移动端自适应px转rem解决方法
文章 1798 0 0 0
发布时间:2019年12月12日

概述

网上看到很多移动端适配的各种方法,由于原来工作中对rem的疏忽,所以决定重新学习rem~

由于移动端特殊性,本文讲的是如何使用rem实现自适应,或叫rem响应式布局,通过使用一个脚本就可以rem自适应,不用再为各种设备宽度不同而烦恼如何实现自适应的问题。

rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算出元素的宽高。1rem=16px(浏览器html的像素,可以设定这个基准值),假如浏览器的html设为64px,则下面的元素则1rem=64px来运算。

第一种:阿里自适应flexible.js

阿里团队开源的一个库。使用flexible.js轻松搞定各种不同的移动端设备兼容自适应问题。

在这里找到了一个精简版的flexible.min.js,可以适配所有的移动端:

代码如下:

designWidth:设计稿的实际宽度值,需要根据实际设置
maxWidth:制作稿的最大宽度值,需要根据实际设置
这段js的最后面有两个参数记得要设置,一个为设计稿实际宽度,一个为制作稿最大宽度,例如设计稿为750,最大宽度为750,则为(750,750)

;(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;
    }
    //要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
    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);

使用方法:·

1.复制上面这段代码到你的页面的头部的script标签的最前面。
2.根据设计稿大小,调整里面的最后两个参数值。
3.使用1rem=100px转换你的设计稿的像素,例如设计稿上某个块是100px300px,换算成rem则为1rem3rem。
上面的代码,如果在uc浏览器下横屏与竖屏转换,发现代码并没有自适应,则通过下面进行解决bug:

已经找到兼容方案,可通过js在页面的head里生成定义了html元素font-size的style元素来解决!

如下:

<style id="rootFontSize">html{font-size: 100px !important;}</style>

注意还加了important来提高权重

该代码版本区别于手淘的rem换算方法。使用的是1rem=100px的换算。·

假如你有一个块是.box{width:120px;height:80px;} 转为rem则为.box{width:1.2rem; height:.8rem;}

基本的HTML模板·

你也可以直接复制下面这个基础的HTML模板。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
        <meta content="yes" name="apple-mobile-web-app-capable">
        <meta content="black" name="apple-mobile-web-app-status-bar-style">
        <meta content="telephone=no" name="format-detection">
        <meta content="email=no" name="format-detection">
        <meta name="description" content="不超过150个字符"/>
        <meta name="keywords" content=""/>
        <meta content="caibaojian" name="author"/>
        <title>前端开发博客</title>
        <link rel="stylesheet" href="base.css">
        <script type="text/javascript">
        //引入该flexible.min.js
        !function(e,t){function n(){
            var n=l.getBoundingClientRect().width;t=t||540,n>t&&(n=t);
            var i=100n/e;r.innerHTML="html{font-size:"+i+"px;}"}
            var i,d=document,o=window,l=d.documentElement,r=document.createElement("style");
            if(l.firstElementChild)
            l.firstElementChild.appendChild(r);
            else{
            var a=d.createElement("div");
            a.appendChild(r),
            d.write(a.innerHTML),
            a=null}n(),
            o.addEventListener("resize",function(){
            clearTimeout(i),i=setTimeout(n,300)},!1),
            o.addEventListener("pageshow",function(e){
            e.persisted&&(clearTimeout(i),i=setTimeout(n,300))},!1),
            "complete"===d.readyState?d.body.style.fontSize="16px":d.addEventListener("DOMContentLoaded",function(e){
            d.body.style.fontSize="16px"},!1)}(750,750);
        </script>
    </head>
    <body>
        <!— 正文 —>
    </body>
</html>

base.css:

body,dl,dd,ul,ol,h1,h2,h3,h4,h5,h6,pre,form,input,textarea,p,hr,thead,tbody,tfoot,th,td{
    margin:0;padding:0;
}
ul,ol{
    list-style:none;
}
a{
    text-decoration:none;
}
html{
    -ms-text-size-adjust:none;
    -webkit-text-size-adjust:none;
    text-size-adjust:none;
}
body{
    line-height:1.5;
    font-size:14px;
}
body,button,input,select,textarea{
    font-family:'helvetica neue',tahoma,'hiragino sans gb',stheiti,'wenquanyi micro hei',\5FAE\8F6F\96C5\9ED1,\5B8B\4F53,sans-serif;
}
b,strong{
    font-weight:bold;
}
i,em{
    font-style:normal;
}
table{
    border-collapse:collapse;
    border-spacing:0;
}
table th,table td{
    border:1px solid #ddd;
    padding:5px;
}
table th{
    font-weight:inherit;
    border-bottom-width:2px;
    border-bottom-color:#ccc;
}
img{
    border:0 none;
    width:auto;
    max-width:100%;
    vertical-align:top;
    height:auto;
}
button,input,select,textarea{
    font-family:inherit;
    font-size:100%;
    margin:0;
    vertical-align:baseline;
}
button,html input[type="button"],input[type="reset"],input[type="submit"]{
    -webkit-appearance:button;
    cursor:pointer;
}
button[disabled],input[disabled]{
    cursor:default;
}
input[type="checkbox"],input[type="radio"]{
    box-sizing:border-box;
    padding:0;
}
input[type="search"]{
    -webkit-appearance:textfield;
    -moz-box-sizing:content-box;
    -webkit-box-sizing:content-box;
    box-sizing:content-box;
}
input[type="search"]::-webkit-search-decoration{
    -webkit-appearance:none;
}
input:focus{
    outline:none;
}
select[size],select[multiple],select[size][multiple]{
    border:1px solid #AAA;
    padding:0;
}
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{
    display:block;
}
audio,canvas,video,progress{
    display:inline-block;
}
body{
    background:#fff;
}
input::-webkit-input-speech-button {
    display: none
}
button,input,textarea{
    -webkit-tap-highlight-color: rgba(0,0,0,0);
}

再次强调一下:·

需要根据你的设计稿的大小来调整脚本最后的两个参数。

})(750, 750);

第一个参数是设计稿的宽度,一般设计稿有640,或者是750,你可以根据实际调整

第二个参数则是设置制作稿的最大宽度,超过750,则以750为最大限制。

第二种:纯js操作html上font-size大小

(function (doc, win) {
    var docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function () {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            if(clientWidth>=750){
                docEl.style.fontSize = 100  (clientWidth / 750) + 'px';
            }else{
                docEl.style.fontSize = 100  (clientWidth / 750) + 'px';
            }
        };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

750是你ui设计图尺寸

评论专区