1. 程式人生 > >CSS中的px與物理像素、邏輯像素、1px邊框問題

CSS中的px與物理像素、邏輯像素、1px邊框問題

情況 這樣的 dep 兩種 事情 pos scree 開心 screen

一直不太清楚CSS中的1px與邏輯像素、物理像素是個什麽關系(作為一名前端感覺很慚愧 -_-!),今天終於花時間徹底弄清楚了,其實弄清楚之後就覺得事情很簡單,但也只有在弄清楚之後,才會覺得簡單(語出《禪與摩托車維修藝術》,哈哈哈哈)。

兩種像素

物理像素:設備屏幕實際擁有的像素點。比如iPhone 6的屏幕在寬度方向有750個像素點,高度方向有1334個像素點,所以iPhone 6 總共有750*1334個物理像素。

邏輯像素:也叫“設備獨立像素”(Device Independent Pixel, DIP),可以理解為反映在CSS/JS代碼裏的像素點數。

設備像素比(Device Pixel Ratio, DPR

):一個設備的物理像素與邏輯像素之比。

像素還分物理和邏輯?這兩個玩意有啥區別?

其實在很久以前,的確是沒區別的,CSS裏寫個1px,屏幕就給你渲染成1個實際的像素點,DPR=1,多麽簡單自然~

但是後來事情起了變化,搞事的就是Retina技術,這種技術使用4個乃至更多物理像素來渲染1個邏輯像素,這樣一來,同樣的CSS代碼設置的尺寸,在Retina和非Retina屏幕上看起來大小是一樣的,但在Retina屏幕上要精細得多。

技術分享圖片

在Retian屏上,DPR不再是1,而是大於1,比如2(iPhone 5 6 7 8)或3(iPhone 6 Plus等一系列Plus)或者為非整數(一些Android機),說不定還會漲。

舉個例子,iPhone 6的物理像素上面已經說了,是750*1334,那它的邏輯像素呢?我們只需在iPhone 6的Safari裏打印一下screen.width和screen.height就知道了,結果是 375*667,這就是它的邏輯像素,據此很容易計算出DRP為2。當然,我們還可以直接通過window.devicePixelRatio這個值來獲取DRP,打印結果是2,符合我們的預期。

奇葩的iPhone 6 Plus

這裏不得不提一下iPhone 6 Plus(以及同尺寸的其他果機),它的實際物理像素點個數是1080*1920,但如果你截個屏,你會發現截屏圖片的寬高是1242*2208;瀏覽器的screen對象會告訴你,6 Plus的邏輯像素是414*736,正好是截屏寬度的三分之一,window.devicePixelRatio值也為3。

所以現在我們有了3種不同的像素值?什麽情況?

是這樣的,iPhone 6 Plus系統定義的屏幕像素就是1242*2208,系統會自動把這些像素點塞進1080*1920個實際像素點來渲染,這個過程對於開發者是透明的,無需理會。

所以對於前端來說,可以直接把1242視為6 Plus的“物理像素”,包括UE小姐姐們出圖也是以1242為標準的,因此不妨把1242*2208稱為6 Plus的“設計像素”。

蘋果這是要鬧那樣?

其實,當初蘋果公司在確定6 Plus的DRP時,糾結了半天:選2吧,同樣的字號在6 Plus上看起來比6更小,不好;選3吧,字又顯得太大了,導致一屏能展示的內容還沒有6多;最適合視覺的DRP值是2.46,但這樣一個數字能把設計師和程序員們逼瘋。最後就想出了引入“設計像素”這樣一個兩全其美的方案,既讓開發者開心,又讓用戶爽,豈不美哉?

1px邊框問題

在蘋果的帶動下,Retina技術在移動設備上已經成了標配,所以前端攻城獅必須直面如下事實:

  1. 你想畫個1px的下邊框,但屏幕硬是塞給你一條寬度為2—3個物理像素的線。
  2. 你沒法像安卓或iOS的同事那樣直接操縱物理像素點。

這就是初級前端面試必考題之“1px邊框問題”的由來。

1px邊框問題的解法千奇百怪,各顯神通,但以我的實踐經驗,最推崇的方法還是利用CSS3的transform: scale,因為簡單直接、適用性和兼容性好。

你不是給我兩個物理像素點嗎?加個transform: scale(0.5),只剩一個點了~

三個物理像素點?那就scale(0.33)!

使用CSS的-webkit-min-device-pixel-ratio媒體查詢可以針對不同的DPR做出處理 ,下面以Less代碼為例:

@media (-webkit-min-device-pixel-ratio:2),(min-device-pixel-ratio:2){
    .border-bt-1px(@color) {
        position: relative;
        &::after {
            position: absolute;
            bottom: 0;
            width: 100%;
            height: 1px;
            background-color: @color;
            transform: scaleY(0.5);
        }
    }
}

上面介紹的是只有一邊的情景,如果是四面都要有框,咋辦?

那就畫個DPR倍大小的矩形框,再scale一下,完事~

至此,本文的關於像素的知識,應是足夠應對一般前端的工作需要了。

CSS中的px與物理像素、邏輯像素、1px邊框問題