1px?0.5px!


1px? 0.5px!

前一段時間剛開發完一個項目,但總感覺界面樣式怪怪的,雖然表面上看起來和設計稿是一樣的,可是就是沒設計稿那種感覺,而且莫名還有一種山寨的氣息,讓我感到很郁悶,找來找去終於發現罪魁禍首——border線寬的問題。

問題產生的原因

關於設備像素的基礎知識,建議去看 《A pixer is not a pixer is not a pixer》

簡單來說就是手機屏幕分辨率越來越高了,同樣大小的一個手機,它的實際物理像素數更多了。現在做移動端開發時一般都要加上一個<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">這種,來禁止縮放,這樣在不同手機上顯示就一樣了。這種情況下我們做一個1px的border時,這個1px實際就是css像素,在2倍分辨率的手機上那就是占用了2個設備像素(device pixer),在3倍尺寸就是占3個設備像素。但是呢,設計師在PS或sketch中進行設計時設計的像素肯定是按設備像素來的(*其實就跟字體一個原理,設計稿字體大小是28px,但實際代碼卻是14px*),所以嚴格來說設計師希望你呈現的那個邊框寬度,就是0.5px的css像素。

解決辦法

1. 利用css3新屬性scale

其實現的關鍵就是利用before或after偽元素,寬高同時設為200%,然后再縮放0.5,自然就是0.5px了

代碼如下:

 

.scale_border {
    positon : relative;
}
.scale_border::after {
    content : "";
    width : 200%;
    height : 200%;
    position : absolute;
    top : 0;
    left : 0;
    border : 1px solid #dedede;
    -webkit-transform : scale(0.5);
            transform : scale(0.5);
    -webkit-transform-origin : 0 0;
            transform-origin : 0 0;
    box-sizing: border-box;
}

2. 利用background-image

如果你問切圖直接用背景圖可不可以?當然可以,雖說這種方法比較笨吧,但也是一種方法。

但我要說的是另外一種--利用背景漸變linear-gradient來實現,具體代碼如下:

.bg_border {
    background-image : linear-gradient(0deg,red,red 50%,transparent 50%);
    background-size: 100% 1px;
    background-repeat: no-repeat;
}

分析:linear-gradient默認方向從上到下,從0deg到50%的地方顏色是邊框顏色,然后下邊一半顏色就是透明了-沒顏色。中間之所以兩個50%寫在一起,是因為這樣就不會有顏色過渡的漸變效果了,看起來更像一條線,涇渭分明;  然后最關鍵的是下邊的background-size: 100% 1px,就是寬度100%,但高度是1px,注意這里的1px自然是css像素了,加上上邊的background-image,實際效果就是一半有顏色,一半那不就是0.5px,然后再去掉repeat,就實現了。

同理如果要寫border-left或border-right一樣的原理,只需改變方向就可以了。

缺點: 只能做但方向的border,如果有個按鈕要加,而且還有圓角,那就無能為力了

 

3.利用rem做單位

首先對rem還不太了解的同學,請點這里《web app變革之rem》

簡單來講,為了完美自適應,rem是一個很好的解決方案,原理就是在剛加載的時候用js判斷屏幕分辨率,根據不同的分辨率動態為html設置不同font-size大小,設置meta的viewport標簽。

如果你覺得麻煩的話,那可以簡單一些,直接引用淘寶的flexible.js,看其源代碼的話會發現其實很簡短,其核心代碼就更少了,在這里我僅提取其部分代碼來做分析,如果感興趣請自行百度。

var doc = windows.document;
var docEl = doc.documentElement;
var metaEl = doc.createElement('meta');
var devicePixelRatio = window.devicePixelRatio;
var dpr = 0, scale = 0;

if(devicePixelRatio == 1){
    dpr = 1;
}else if (devicePixelRatio == 2){
    dpr = 2;
}else if (devicePixelRatio == 3){
    dpr = 3;
}
scale = 1/dpr;

metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
docEl.firstElementChild.appendChild(metaEl);

function refreshRem(){
    var width = docEl.getBoundingClientRect().width;
    if (width / dpr > 540) {
        width = 540 * dpr;
    }
    var rem = width / 10;
    docEl.style.fontSize = rem + 'px';
    flexible.rem = win.rem = rem;
};
refreshRem();

解釋一下,就是先獲取設備縮放比devicePixelRatio;然后根據縮放比來設定viewport的值,這樣導致的結果就是無論是哪個設備,1px所表示的永遠是1個設備像素,即該設備的最小像素,用法就更簡單了

//直接使用px就能實現
.rem_border {
    border : 1px solid #dedede;
}

優點: 目前最優解決方案,兼容性強,即使有導圓角也能輕松應付

缺點: 對舊項目改動較大,不易改動

 

持續測試中~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM