Rem 等比適配始末

Viewport 等比適配始末 說過使用 Viewport 來實現等比適配的例子,本文詳解等比適配的另外一種方式javascript

推導

拿到一個寬度爲 vWidth 的視覺稿
設設備屏幕寬度爲 dWidth
在視覺稿上量得一個元素的寬度爲 eleVWidth
那麼要實現按照寬度等比適配,在各類設備中元素的實際寬度 x 將知足公式css

//等比
    eleVWidth/vWidth = X/dWidth;

    //咱們的目的是求X
    X = (eleVWidth/vWidth)dWidth;複製代碼

拿到視覺稿以後,eleVWidth 和 vWidth 都已經固定了,可是 dWidth 在不一樣的設備中確實不一樣的,並且須要實際運行的時候咱們才能拿到 dWidth,這個時候就要利用 rem 的特性了,咱們經過阻塞運行的 js 動態設置 rem,使得rem=dWdith/10,套入剛纔的公式:html

X=(eleVWidth/vWidth)*10*rem

    //體如今css中
    .className {
        width: (eleVWidth/vWidth)*10 rem
    }複製代碼

爲何設置是 dWdith/10 呢?方便計算而已,固然也能夠除以別的基數,可是儘可能不要讓 rem 過小,有兼容性問題java

動態設置rem

這段 css 須要放在 body 標籤的開始位置,由於 rem 值要儘量早的設置成功,避免無謂的重排重繪(有些設備中若元素樣式已經生效,動態改變 rem 未必能起做用,因此這個動做更須要提早)android

<body>
        <script> (function() { var ua = window.navigator.userAgent; var docEl = document.documentElement; var html = document.querySelector('html'); var isAndorid = /Android/i.test(ua); var dpr = window.devicePixelRatio || 1; var rem = docEl.clientWidth / 10; // 設置 rem 基準值 html.style.fontSize = rem + 'px'; // Nexus 5 上 rem 值不許, // 如:設置100px,getComputedStyle 中的值卻爲 85px,致使頁面錯亂 // 這時須要檢查設置的值和計算後的值是否同樣, // 不同的話從新設置正確的值 var getCPTStyle = window.getComputedStyle; var fontSize = parseFloat(html.style.fontSize, 10); var computedFontSize = parseFloat(getCPTStyle(html)['font-size'], 10); if (getCPTStyle && Math.abs(fontSize - computedFontSize) >= 1) { html.style.fontSize = fontSize * (fontSize / computedFontSize) + 'px'; } // 設置 data-dpr 屬性,留做的 css hack 之用 html.setAttribute('data-dpr', dpr); // 安卓平臺額外加上標記類 if (isAndorid) { html.setAttribute('data-platform', 'android'); } })(); </script>
        ...
    </body>複製代碼

css 中應該怎麼寫

若是每在視覺稿上量出一個值,在寫到樣式文件以前都得經過那個公式計算一翻,那絕對不是一個好策略,咱們但願量到啥就寫啥webpack

使用 less,sass 等 css 預處理器的函數web

//設計稿爲640
    @function rem($val) {
        @return $val/64 * 1rem;;
    }

    //設計稿爲750
    @function rem750($val) {
        @return $val/75 * 1rem;
    }

    //使用
    .className {
        width: @rem(100);
    }複製代碼

也可使用 webpack-loader,例如:change-rem-loader,這個 loader 代碼作的事也是上述的轉化計算(寫一個 webpack loader 並不複雜,你能夠本身寫一個符合本身狀況的 loader)npm

 'use strict';
    module.exports = function(source) {
        source = source.replace(/rem(\d*)\((.*?)\)/g, function(match, type, value) {
            var divVal;

            // 不作 try catch,及早發現錯誤以避免形成故障
            switch (type) {
                // 1080寬度的設計稿,rem1080(value)
                case '1080':
                    divVal = 108;
                    break;
                    // 默認爲750寬度的設計稿,rem(value)
                case '750':
                    divVal = 75;
                    break;
                default:
                    divVal = 64;
            }

            return (value / divVal).toFixed(6) + 'rem';
        });
        return source;
    }複製代碼

這樣以後,咱們 css 一樣能夠這樣寫(如何讓 loader 起做用不是本文的範圍)sass

.className {
        width: rem(100);
    }複製代碼

也許你的工程技術棧裏面,使用的不是 webpack,也沒有使用 less、sass 等預處理器,那你能夠根據你的實際狀況去尋找一種預處理方案,只要達到推導公式的效果就能夠了。
什麼?沒有合適的方案,那你是時候充充電了less

期待您的關注~~

相關文章
相關標籤/搜索