盤點移動端適配方案

盤點移動端適配方案

移動端.png

作為開發(fā)者柠横,在手機(jī)移動端做適配的時候會出現(xiàn)很多問題:最不希望用戶看到的就是橫向滾動條笼痛。其次是文字(圖片等)的大小不能一成不變祈秕,要根據(jù)用戶設(shè)備的物理像素調(diào)節(jié)大小唯蝶。

手機(jī)瀏覽器是把頁面放在一個虛擬的"窗口"(viewport)中,通常這個虛擬的"窗口"(viewport)比屏幕寬详瑞,這樣就不用把每個網(wǎng)頁擠到很小的窗口中(<u>這樣會破壞沒有針對手機(jī)瀏覽器優(yōu)化的網(wǎng)頁的布局</u>)掂林,用戶可以通過平移和縮放來看網(wǎng)頁的不同部分。

這就該輪到meta標(biāo)簽出場了坝橡。meta標(biāo)簽的作用是讓當(dāng)前viewport的寬度等于設(shè)備的寬度泻帮,同時不允許用戶手動縮放。也許允不允許用戶縮放计寇,不同的網(wǎng)站有不同的要求锣杂,但讓viewport的寬度等于設(shè)備的寬度,這個應(yīng)該是大家都想要的效果番宁,如果你不這樣的設(shè)定的話元莫,就會使用那個比屏幕寬的默認(rèn)viewport,也就是說會出現(xiàn)橫向滾動條贝淤;

  • 設(shè)置Viewport

一個常用的針對移動網(wǎng)頁優(yōu)化過的頁面的 viewport meta 標(biāo)簽大致如下:

<meta name="viewport" content="width=device-width, initial-scale=1.0">
  • width

控制 viewport 的大小柒竞,可以指定的一個值,如 600播聪,或者特殊的值,如 device-width 為設(shè)備的寬度(單位為縮放為 100% 時的 CSS 的像素)布隔。

  • initial-scale

初始縮放比例离陶,也即是當(dāng)頁面第一次 load 的時候縮放比例。

  • user-scalable

用戶是否可以手動縮放(默認(rèn)設(shè)置為no衅檀,因為我們不希望用戶放大縮小頁面)

  • minimum-scale

允許用戶縮放到的最小比例(默認(rèn)設(shè)置為1.0)

  • maximum-scale

允許用戶縮放到的最大比例(默認(rèn)設(shè)置為1.0)

一招刨、rem適配

rem(font size of the root element)是指相對于根元素的字體大小的單位。簡單的說它就是一個相對單位哀军〕量簦看到rem大家一定會想起em單位,em(font size of the element)是指相對于父元素的字體大小的單位杉适。它們之間其實很相似谎倔,只不過一個計算的規(guī)則是依賴根元素一個是依賴父元素計算。

正是因為它適配的標(biāo)準(zhǔn)是根元素的字體大小猿推,而不同的手機(jī)型號對于根元素的規(guī)定不同[1]捌肴,這便增加了很多不必要的判斷。

二状知、vw適配

vw(viewpoint width),即視窗寬度孽查,1vw等于視窗寬度的1%

計算方式(以750的設(shè)計稿為準(zhǔn)):設(shè)計圖中元素固定的大小(px) * 100 / 750 => vw

eg : 90px轉(zhuǎn)化為vw : 90 * 100 / 750 => 12vw

如果是375的設(shè)計稿需要乘以2 : 設(shè)計圖中元素固定的大小(px) * 2 * 100 / 750 => vw

不難看出,使用的時候仍需進(jìn)行大量的計算盲再。

三、vw+rem適配

因為vw的比例需要動態(tài)地計算洲胖,而rem做移動端布局的時候剛好需要動態(tài)地改變,因此我們只要稍加計算绿映,將根元素的字體大小換成vw即可擒滑。

  • 640的設(shè)計稿

    320px == 100vw ; 1px == 100 / 320 == 0.3125vw ; 100px == 31.25vw;

    此時設(shè)置根元素字體大小html,body{font-size:31.25vw} , => 1rem == 100px; =>1px == 0.01rem;

    所以丐一,根據(jù)設(shè)計稿的像素計算時,只需將px除以100即可

    計算方式:元素尺寸 / 2 / 100 = rem

    320的設(shè)計稿計算方式:元素尺寸 / 100 = rem

  • 750的設(shè)計稿

    375px == 100vw ; 1px == 100 / 375 == 0.26666vw ; 100px == 26.6666vw

    出現(xiàn)了小數(shù)點后除不盡的情況……為了將結(jié)果它轉(zhuǎn)換成整數(shù) 120px == 32vw此時設(shè)置根元素字體大小html,body{font-size:32vw} , 計算方式也發(fā)生改變:元素尺寸 / 2 / 120 = rem

    375的設(shè)計稿計算方式:元素尺寸 / 120 = rem

以上面的幾種設(shè)計稿為例淹冰,尤其是750的設(shè)計稿居多库车,大多數(shù)情況下根據(jù)元素的尺寸 / 120 ,這么難以計算的數(shù)字樱拴,還是交給插件來做吧柠衍。以VScode中的cssrem為例:

注意:配置完參數(shù)之后,重啟軟件

cssrem.png

四晶乔、flexible.js布局(推薦)

通過flexible.js實現(xiàn)了rem自適應(yīng)珍坊,有了flexible.js,我們就不必再為移動端各種設(shè)備兼容煩惱正罢。通過rem與px的換算阵漏,把設(shè)計稿從px轉(zhuǎn)到rem。再也不用為各種設(shè)備橫行而擔(dān)憂翻具。

rem是相對于根元素html履怯,這樣就意味著,我們只需要在根元素確定一個px字號裆泳,則可以來算出元素的寬高叹洲。1rem=16px(瀏覽器html的像素,可以設(shè)定這個基準(zhǔn)值)晾虑,假如瀏覽器的html設(shè)為64px疹味,則下面的元素則1rem=64px來運(yùn)算仅叫。

阿里團(tuán)隊開源的一個庫。使用flexible.js輕松搞定各種不同的移動端設(shè)備兼容自適應(yīng)問題糙捺。

  1. 刪除viewport的meta標(biāo)簽诫咱,替換為下面的JS代碼

    (function (win, lib) {
        var doc = win.document;
        var docEl = doc.documentElement;
        var metaEl = doc.querySelector('meta[name="viewport"]');
        var flexibleEl = doc.querySelector('meta[name="flexible"]');
        var dpr = 0;
        var scale = 0;
        var tid;
        var flexible = lib.flexible || (lib.flexible = {});
    
        if (metaEl) {
            //        console.warn('將根據(jù)已有的meta標(biāo)簽來設(shè)置縮放比例');
            var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
            if (match) {
                scale = parseFloat(match[1]);
                dpr = parseInt(1 / scale);
            }
        } else if (flexibleEl) {
            var content = flexibleEl.getAttribute('content');
            if (content) {
                var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
                var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
                if (initialDpr) {
                    dpr = parseFloat(initialDpr[1]);
                    scale = parseFloat((1 / dpr).toFixed(2));
                }
                if (maximumDpr) {
                    dpr = parseFloat(maximumDpr[1]);
                    scale = parseFloat((1 / dpr).toFixed(2));
                }
            }
        }
    
        if (!dpr && !scale) {
            var isAndroid = win.navigator.appVersion.match(/android/gi);
            var isIPhone = win.navigator.appVersion.match(/iphone/gi);
            var devicePixelRatio = win.devicePixelRatio;
            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 {
                // 其他設(shè)備下,仍舊使用1倍的方案
                dpr = 1;
            }
            scale = 1 / dpr;
    
        }
    
        docEl.setAttribute('data-dpr', dpr);
        if (!metaEl) {
            metaEl = doc.createElement('meta');
            metaEl.setAttribute('name', 'viewport');
            metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
            if (docEl.firstElementChild) {
                docEl.firstElementChild.appendChild(metaEl);
            } else {
                var wrap = doc.createElement('div');
                wrap.appendChild(metaEl);
                doc.write(wrap.innerHTML);
            }
        }
    
        function refreshRem() {
            var width = docEl.getBoundingClientRect().width;
    
            if (width / dpr > 768) {
                width = 768 * dpr;
            }
            var rem = width / 7.5;
            docEl.style.fontSize = rem + 'px';
            flexible.rem = win.rem = rem;
        }
    
        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 = 12 * dpr + 'px';
        } else {
            doc.addEventListener('DOMContentLoaded', function (e) {
                doc.body.style.fontSize = 12 * dpr + 'px';
            }, false);
        }
    
        refreshRem();
    
        flexible.dpr = win.dpr = dpr;
        flexible.refreshRem = refreshRem;
        flexible.rem2px = function (d) {
            var val = parseFloat(d) * this.rem;
            if (typeof d === 'string' && d.match(/rem$/)) {
                val += 'px';
            }
            return val;
        }
        flexible.px2rem = function (d) {
            var val = parseFloat(d) / this.rem;
            if (typeof d === 'string' && d.match(/px$/)) {
                val += 'rem';
            }
            return val;
        }
    
    })(window, window['lib'] || (window['lib'] = {}));
    
    
  2. 以750設(shè)計稿為準(zhǔn)签钩,元素尺寸 / 100 = rem ; 以375設(shè)計稿為準(zhǔn)掏呼,元素尺寸 * 2 / 100 = rem ,因為flexble中會再除以2铅檩,所以這里乘以2將其抵消憎夷。

參考博客1 前端開發(fā)博客


  1. 根字體大小:iPhone5s:12px iPhone6S:14px iPhone6P:16px ?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末昧旨,一起剝皮案震驚了整個濱河市拾给,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌兔沃,老刑警劉巖蒋得,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異额衙,居然都是意外死亡怕吴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門疏之,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事丙曙。” “怎么了扯旷?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵索抓,是天一觀的道長毯炮。 經(jīng)常有香客問我耸黑,道長,這世上最難降的妖魔是什么为迈? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任缺菌,我火速辦了婚禮,結(jié)果婚禮上耿战,老公的妹妹穿的比我還像新娘。我一直安慰自己剂陡,他們只是感情好租冠,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纤泵,像睡著了一般镜粤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肉渴,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機(jī)與錄音循狰,去河邊找鬼券勺。 笑死,一個胖子當(dāng)著我的面吹牛关炼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播儒拂,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼见转!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起池户,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赊抖,沒想到半個月后寨典,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡报亩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年井氢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劲件。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡约急,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厌蔽,到底是詐尸還是另有隱情,我是刑警寧澤奴饮,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布戴卜,位于F島的核電站,受9級特大地震影響叉瘩,放射性物質(zhì)發(fā)生泄漏粘捎。R本人自食惡果不足惜危彩,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一汤徽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谒府,春花似錦浮毯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芳誓。三九已至,卻和暖如春锹淌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赂摆。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工憎妙, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厘唾。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像喷楣,于是被迫代替她去往敵國和親鹤树。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 方案一: 最新方案:(隆重推薦) 1曲伊、下載MateHandler.js,并引入頁面2坟募、head里加入 3、設(shè)置bo...
    晨光2016閱讀 891評論 0 0
  • 移動端適配方案:1)viewport(scale=1/dpr)2)rem3)flex4)vm/vh一涤妒、什么是移動端...
    puxiaotaoc閱讀 43,054評論 3 56
  • @description 該方法是用于移動端適配功能赚哗, 結(jié)合淘寶的適配方案flexible + rem 實現(xiàn)適配,...
    王小傲閱讀 436評論 0 0
  • 手淘的rem適配js flex.js ;(function(win, lib) { var doc = win.d...
    嘗了又嘗閱讀 373評論 0 0
  • 這是一篇“讀書筆記”贿讹,原文是萬維鋼老師的專欄《精英日課》的一篇文章扩所,與題目同名。 話不多說祖屏,直接開始! 萬老師從四...
    小小Mark閱讀 405評論 3 0