利用vw+rem實現移動web適配佈局

村長不太忙發表於2018-12-02

基本概念

1、單位

Px(CSS pixels)

  • 畫素 (px) 是一種絕對單位(absolute units), 因為無論其他相關的設定怎麼變化,畫素指定的值是不會變化的
  • 其實是相對於某個裝置而言的,不同裝置指定的值大小還是有區別的

em

  • 1em與當前元素的字型大小相同(更具體地說,一個大寫字母M的寬度)。CSS樣式被應用之前,瀏覽器給網頁設定的預設基礎字型大小是16畫素,這意味著對一個元素來說1em的計算值預設為16畫素。但是要小心—em單位是會繼承父元素的字型大小,所以如果在父元素上設定了不同的字型大小,em的畫素值就會變得複雜。現在不要過於擔心這個問題,我們將在後面的文章和模組中更詳細地介紹繼承和字型大小設定。em是Web開發中最常用的相對單位。

ex, ch

  • 分別是小寫x的高度和數字0的寬度。這些並不像em那樣被普遍使用或很好地被支援。

rem

  • REM(root em)和em以同樣的方式工作,但它總是等於預設基礎字型大小的尺寸;繼承的字型大小將不起作用,所以這聽起來像一個比em更好的選擇,雖然在舊版本的IE上不被支援 檢視關於跨瀏覽器支援 Debugging CSS.)

vw,vh

  • 分別是視口寬度的1/100和視口高度的1/100,其次,它不像rem那樣被廣泛支援。 還有vmin,vmax...

百分比

2. rem 和 vw 相容對比

  • rem

    rem

  • vw

    vm

3、關於window.devicePixelRatio

mdn

  • 此屬性返回當前顯示裝置的物理畫素解析度與CSS畫素解析度的比值。該值也可以被解釋為畫素大小的比例:即一個CSS畫素的大小相對於一個物理畫素的大小的比值。

那麼什麼是裝置的物理畫素?

  • 物理畫素(physical pixel):裝置能控制顯示的最小單位。裝置獨立畫素(DIP,device-independent pixel,density-independent pixel):獨立於裝置的用於邏輯上衡量畫素的單位

  • 對於前端來說,可以理解成在裝置上能設定的最小值。如在dpr = 1 最小值1px; dpr = 2 最小值為0.5px

PPI(pixel per inch)

  • 每英寸有多少個畫素點(裝置畫素點),PPI越高,畫質越好。

公式

// w: 橫向pixel
// h: 縱向pixel
// inch: 螢幕尺寸
PPI = Math.sqrt(w * w + h * h) / inch

console.log(Math.ceil(Math.sqrt(1920 * 1920 + 1080 * 1080) / 5.5))
// 然而我並不明白怎麼要這樣算 不是應該是 w * h / inch ?????
複製程式碼

retina 螢幕

具備足夠高畫素密度而使得人體肉眼無法分辨其中單獨畫素點的液晶屏

3、移動適配注意的點

  1. 螢幕尺寸不一樣的適配問題

    • 這個可以藉助vw完美解決
  2. 圖片模糊問題

    • 圖片用三倍圖 可以保證清晰,推薦用兩倍圖+webp格式 開發和顯示效果折中的結果
  3. 1px 顯示問題

    • 方法很多
  4. api不支援的相容問題

    • vw不支援的相容
  5. 高清顯示

    • 是否影響渲染效能??待考證
    • 縮放是否可以是網頁更高清?

利用vw+rem實現移動web適配佈局

  1. 第三方元件庫相容問題
  2. 富文字顯示問題
  3. 前端程式碼遷移單位不一致問題

適配方案

1、經典的flexble.js方案

存在問題

  • 1、iframe 問題
  • 2、富文字問題
// vue指令
// 1. 先獲取dpr 2獲取每個文件物件的字型大小 乘以dpr
Vue.directive('richtext', (el, binding) => {
    Vue.nextTick(() => {
        let dpr = document.querySelector('html').getAttribute('data-dpr')
        let f = (dom) => {
            let fontPx = dom.style && dom.style.fontSize
            if (fontPx) {
                fontPx = fontPx.substr(0, fontPx.length - 2) * parseInt(dpr)
                dom.style.fontSize = fontPx + 'px'
            }
            if (dom.childNodes.length > 0) {
                for (let i = 0; i < dom.childNodes.length; i++) {
                    f(dom.childNodes[i])
                }
            }
        }
        f(el)
    })
})
// 使用方法 
.richtext(v-html="content" v-richtext='')
複製程式碼

3、高清方案存在的誤區 dpr越高越清晰 是源自裝置本身和縮放關係不大或者說當dpr為1時清晰度已經足夠了,不需要再通過縮放來是網頁顯示更清晰(實踐總結,未找到資料支援) 4、相容問題 juejin.im/post/5b9cb9…

2、vw方案

參考

3、rem + vw (推薦方案)

設定html根font-size的值 // 設計稿 750 * 1334

html {
  height: 100%;
  font-size: 50px; // 向下相容 不止vw時候 寫死font-size
  font-size: 13.33333333vw; // 7.5rem === 100vw
  margin: 0 auto;
}


@media (min-width: 560px) { // pc相容
  html,body {
    font-size: 54px;
    max-width: 540px;
  }
}

@media (max-width: 1024px) { // ipad相容:ipad最大1024px
  html,body {
    max-width: 1024px;
  }
}
複製程式碼

1px顯示問題 物理畫素 dpr>=2 取2倍

.border-bottom {
  position: relative;
  &::after {
    content: '';
    position: absolute;
    z-index: 1;
    pointer-events: none;
    background-color: red;
    height: 1px;
    left: 0;
    right: 0;
    bottom: 0;
    @media only screen and (min-resolution: 2dppx) { // 非標準的
      -webkit-transform: scaleY(0.5);
      -webkit-transform-origin: 50% 0%;
    }
  }
}
// only操作符僅在媒體查詢匹配成功的情況下被用於應用一個樣式,這對於防止讓選中的樣式在老式瀏覽器中被應用到
// -webkit-device-pixel-ratio 是一個非標準的布林型別CSS媒體型別,是標準 
// resolution 媒體型別的一個替代方案.
複製程式碼

單位要怎麼寫

方法一:postcss-px2rem(vue-cli3)

這裡不推薦 因為px2rem: 寫px時需要加上 /*no*/ 感覺比較麻煩

const px2rem = require('postcss-px2rem')
const postcssPx2rem = new px2rem({
  remUnit: 50 // 基準大小
})
css: {
    loaderOptions: {
      postcss: {
        plugins: [postcssPx2rem]
      },
    }
  },
複製程式碼

方法二:目前方案是直接寫 7.5rem=100vw 設計稿除以100即可

方法三:px2rem的編輯器外掛如vscode的cssrem

除不盡的問題 (calc) 涉及到相容問題

總結 vw + rem的好處

  • 實現簡單
    • 不依賴外掛及第三方庫
    • 幾行css程式碼 就可以實現
  • 開發方便
    • 100vw === 設計稿 / 100 rem 方便換算
    • 不影響px使用,完美相容第三方元件庫
    • 不存在富文字和iframe等相容問題

相關文章