移動前端適配方法總結

所謂前端適配,就是爲了讓移動設計稿在大部分的移動設備上看起來有一致的展示效果,目前比較流行的方法有兩種。各有利弊,使用第一種在某些瀏覽器的webview裏面會出現兼容問題,而且對於1像素會無法渲染。而用rem的方案在背景和字體上也會有某些問題。

方案一:強制meta viewport的寬度爲設計稿的寬度

把下面的代碼放在頭部,然後製作稿跟PC上一樣的製作就行

// 根據設計稿的寬度來傳參 比如640 750 1125
!function(designWidth){
    if (/Android(?:\s+|\/)(\d+\.\d+)?/.test(navigator.userAgent)) {
        var version = parseFloat(RegExp.$1);
        if (version > 2.3) {
            var phoneScale = parseInt(window.screen.width) / designWidth;
            document.write('<meta name="viewport" content="width=' + designWidth + ',minimum-scale=' + phoneScale + ',maximum-scale=' + phoneScale + ', target-densitydpi=device-dpi">');
        } else {
            document.write('<meta name="viewport" content="width=' + designWidth + ',target-densitydpi=device-dpi">');
        }
    } else {
        document.write('<meta name="viewport" content="width=' + designWidth + ',user-scalable=no,target-densitydpi=device-dpi,minimal-ui,viewport-fit=cover">');
    }
}(640);
demo
<!doctype HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta content="telephone=no" name="format-detection" />
<title>model</title>
<script type="text/javascript">
// 根據設計稿的寬度來傳參 比如640 750 1125
!function(e){if(/Android(?:\s+|\/)(\d+\.\d+)?/.test(navigator.userAgent)){var t=parseFloat(RegExp.$1);if(t>2.3){var i=parseInt(window.screen.width)/e;document.write('<meta name="viewport" content="width='+e+",minimum-scale="+i+",maximum-scale="+i+', target-densitydpi=device-dpi">')}else{document.write('<meta name="viewport" content="width='+e+',target-densitydpi=device-dpi">')}}else{document.write('<meta name="viewport" content="width='+e+',user-scalable=no,target-densitydpi=device-dpi,minimal-ui,viewport-fit=cover">')}}(640);
</script>
<style>
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;font-size:32px;}
body{font-size:32px;line-height:1.5;}
body,button,input,select,textarea{font-family:'helvetica neue',tahoma,'hiragino sans gb',stheiti,'wenquanyi micro hei',5FAE8F6F96C59ED1,5B8B4F53,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:auto9;max-width:100%;vertical-align:top;}
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;}
@media screen and (-webkit-min-device-pixel-ratio:0){
input{line-height:normal!important;}
}
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;}
</style>
</head>
<body>
    <!-- 頁面結構寫在這裏 -->
    <!-- 頁面結構寫在這裏 -->
    <!-- 頁面結構寫在這裏 -->
    <!-- 頁面結構寫在這裏 -->
</body>
</html>
方案2:使用淘寶的rem精簡版

計算尺寸時,只需要將對應的尺寸除以100。

源碼:

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

    function refreshRem() {
        // var width = parseInt(window.screen.width); // uc有bug
        var width = docEl.getBoundingClientRect().width;
        if (!maxWidth) {
            maxWidth = 540;
        };
        if (width > maxWidth) { // 淘寶做法:限制在540的屏幕下,這樣100%就跟10rem不一樣了
            width = maxWidth;
        }
        var rem = width * 100 / designWidth;
        // var rem = width / 10; // 如果要兼容vw的話分成10份 淘寶做法
        //docEl.style.fontSize = rem + "px"; //舊的做法,在uc瀏覽器下面會有切換橫豎屏時定義了font-size的標籤不起作用的bug
        remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
    }

    // 設置 viewport ,有的話修改 沒有的話設置
    metaEl = doc.querySelector('meta[name="viewport"]');
    // 20171219修改:增加 viewport-fit=cover ,用於適配iphoneX
    metaElCon = "width=device-width,initial-scale=1,maximum-scale=1.0,user-scalable=no,viewport-fit=cover";
    if(metaEl) {
        metaEl.setAttribute("content", metaElCon);
    }else{
        metaEl = doc.createElement("meta");
        metaEl.setAttribute("name", "viewport");
        metaEl.setAttribute("content", metaElCon);
        if (docEl.firstElementChild) {
            docEl.firstElementChild.appendChild(metaEl);
        }else{
            var wrap = doc.createElement("div");
            wrap.appendChild(metaEl);
            doc.write(wrap.innerHTML);
            wrap = null;
        }
    }

    //要等 wiewport 設置好後才能執行 refreshRem,不然 refreshRem 會執行2次;
    refreshRem();

    if (docEl.firstElementChild) {
        docEl.firstElementChild.appendChild(remStyle);
    } else {
        var wrap = doc.createElement("div");
        wrap.appendChild(remStyle);
        doc.write(wrap.innerHTML);
        wrap = null;
    }

    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);
demo
<!doctype HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta content="telephone=no" name="format-detection" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0,user-scalable=no,viewport-fit=cover"/>
<title>lib.flexible 簡化版</title>
<script type="text/javascript">
(function(e,t){var i=document,n=window;var l=i.documentElement;var r,a;var d,o=document.createElement("style");var s;function m(){var i=l.getBoundingClientRect().width;if(!t){t=540}if(i>t){i=t}var n=i*100/e;o.innerHTML="html{font-size:"+n+"px;}"}r=i.querySelector('meta[name="viewport"]');a="width=device-width,initial-scale=1,maximum-scale=1.0,user-scalable=no,viewport-fit=cover";if(r){r.setAttribute("content",a)}else{r=i.createElement("meta");r.setAttribute("name","viewport");r.setAttribute("content",a);if(l.firstElementChild){l.firstElementChild.appendChild(r)}else{var c=i.createElement("div");c.appendChild(r);i.write(c.innerHTML);c=null}}m();if(l.firstElementChild){l.firstElementChild.appendChild(o)}else{var c=i.createElement("div");c.appendChild(o);i.write(c.innerHTML);c=null}n.addEventListener("resize",function(){clearTimeout(s);s=setTimeout(m,300)},false);n.addEventListener("pageshow",function(e){if(e.persisted){clearTimeout(s);s=setTimeout(m,300)}},false);if(i.readyState==="complete"){i.body.style.fontSize="16px"}else{i.addEventListener("DOMContentLoaded",function(e){i.body.style.fontSize="16px"},false)}})(750,750);
</script>
<style>
/*
需要注意的是:
樣式的reset中需先設置html字體的初始化大小爲50px,這是爲了防止js被禁用或者加載不到或者執行錯誤而做的兼容
樣式的reset中需先設置body字體的初始化大小爲16px,這是爲了讓body內的字體大小不繼承父級html元素的50px,而用系統默認的16px
*/
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;font-size:50px;}
body{line-height:1.5;font-size:16px;}
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\9;max-width:100%;vertical-align:top;}
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;}
@media screen and (-webkit-min-device-pixel-ratio:0){
input{line-height:normal!important;}
}
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;}


.g-doc{width:6.4rem;margin:0px auto;}

</style>
</head>
<body>
    <div class="g-doc">
        <!-- 頁面結構寫在這裏 -->
        <!-- 頁面結構寫在這裏 -->
        <!-- 頁面結構寫在這裏 -->
        <!-- 頁面結構寫在這裏 -->
    </div>
</body>
</html>

原創文章:移動前端適配方法總結
原文出處:前端開發博客 (http://caibaojian.com/mobile-responsive.html)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章