天天看點

【CSS】872- 淺析rem布局方案

一些像素概念

  • 實體像素:即實際的每一個實體像素,也就是移動裝置上每一個實體顯示單元(點)
  • 裝置邏輯像素(

    css

    中的

    px

    ):可以了解為一個虛拟的相對的顯示塊,與實體像素有着一定的比例關系,也就是下面的裝置像素比
  • 裝置像素比(

    dpr

    ):= 實體像素 / 裝置獨立像素(

    px

    )
如果

dpr

1

的話,那麼

1px = 1實體像素

x

y

軸加起來就是

1

【CSS】872- 淺析rem布局方案
如果

dpr

2

的話,那麼

1px = 2

實體像素,

x

y

軸加起來就是

4

【CSS】872- 淺析rem布局方案

以此類推

在js中可以通過

window.devicePixelRatio

擷取目前裝置的

dpr

這裡說明一下,無論

dpr

多大,

1px

的大小通常來說是一緻的,這也就意味着,随着

dpr

的增大,實體像素點會越來越小,這樣才能容納更多的實體像素,才能更高清,更

retina

【CSS】872- 淺析rem布局方案

說完基本概念,來說一下幾個問題:

retina屏圖檔模糊

首先普及一下位圖像素:一個位圖像素是圖檔的最小資料單元,每一個單元都包含具體的顯示資訊(色彩,透明度,位置等等)

那為什麼在dpr高的retina屏上反而會模糊呢?看圖~

【CSS】872- 淺析rem布局方案

1dpr

的螢幕上,位圖像素和實體像素一一對應沒什麼問題,但是在

retina

屏上,由于一個

px

4

個甚至更多的實體像素組成,并且單個位圖像素不能進一步分割,是以會出現就近取色的情況,如果取色不均,那麼就會導緻圖檔模糊。

對于這種情況,隻能采用

@2x

@3x

這樣的倍圖來适配高清展示,這樣側向說明了為什麼照着

iphone6

做的

ui

稿不是

375

,而是

750

的問題。

雖然這樣在

dpr

1

的螢幕上會導緻

1

個實體像素上有

4

個位圖像素,但是這種情況的取色算法更優,影響不大,不做讨論。

1px的粗細問題

由于

1px

的實際大小是一樣的,隻是裡面的實體像素數量不同,是以如果直接寫

1px

是沒問題的,不會出現粗細不同的情況,但是這樣一來

retina

的優勢也

rem

的作用也就沒了,其實還是

dpr

的問題,

dpr

1

,那麼

1px

就是一個實體像素,但是在

retina

中。

1px

實際可能有

4

9

個實體像素,

ui

想要的其實是

1

個實體像素,而不是1px,不過由于不是素所有的手機都能适配

0.x

,是以曲線救國,采用

scale

縮放或者設定

meta

都可以
【CSS】872- 淺析rem布局方案

viewport

三個概念

  • layout viewport

  • visual viewport

  • ideal viewport

layout viewport

最開始,

pc

上的頁面是無法再移動端正常顯示的,因為螢幕太小,會擠作一團,是以就有了

viewport

的概念,又稱布局視口(虛拟視口),這個視口大小接近于

pc

,大部分都是

980px

visual viewport

有了布局視口,還缺一個承載它的真是視口,也就是移動裝置的可視區域-視覺視口(實體視口),這個尺寸随着裝置的不同也有不同。這樣在視覺視口中建立了一個布局視口,類似

overscroll:scroll;

這樣,可以通過滾動拖拽、縮放擴大進行較好的通路體驗

ideal viewport

像上面的體驗在早些年可能比較多,但是近幾年幾乎很少了,還是歸咎于使用者體驗,是以,我們還需要一個視口-理想視口(同樣是虛拟視口),不過這個理想視口的大小是等于布局視口的,這樣使用者就能得到更好的浏覽體驗。

一個特性

viewport

有六種可以設定的常用屬性:
  • width

    :定義

    layout viewport

    的寬度,如果不設定,大部分情況下預設是

    980

  • height

    :非常用
  • initial-scale

    :可以以某個比例将頁面縮放\放大,你也可以用它來設定

    ideal viewport

<meta name='viewport' content='initial-scale=1' />
           

複制

  • maximum-scale

    :限制最大放大比例
  • minimum-scale

    :限制最小縮小比例
  • user-scalable

    :是否允許使用者放大\縮小頁面,預設為

    yes

rem适配方案

先說原理,通過

meta

修正

1px

對應的實體像素數量,在根據統一的設計稿來生成

html

上的動态

font-size

,根據

dpr

構造字型等誤差較大的樣式的

mixin

// 第一版:
function initRem() {
  const meta = document.querySelector('meta[name="viewport"]');;
  const html = document.documentElement;
  const cliW = html.clientWidth;
  const dpr = window.devicePixelRatio || 1;
  meta.setAttribute('name', 'viewport');
  meta.setAttribute(
      'content',
      `width=${cliW * dpr}, initial-scale=${1 /
          dpr} ,maximum-scale=${1 / dpr}, minimum-scale=${1 /
          dpr},user-scalable=no`
  );
  html.setAttribute('data-dpr', dpr);
  // 這樣計算的好處是,你可以直接用ui的px/100得到的就是rem大小,友善快捷,無需mixin
  html.style.fontSize = 10 / 75 * cliW * dpr + 'px';
}
initRem();
window.onresize = window.onorientationchange = initRem();
           

複制

對于引入的第三方ui元件,需要使用px2rem轉換工具去做整體轉換,比如

postcss-pxtorem

:https://github.com/cuth/postcss-pxtorem