移動端 1px 像素問題及解決辦法

前言:在移動端web開發(fā)中,UI設計稿中設置邊框為1像素,前端在開發(fā)過程中如果出現(xiàn)border:1px,測試會發(fā)現(xiàn)在某些機型上亿遂,1px會比較粗,即是較經(jīng)典的 移動端1px像素問題渺杉。


作者推薦使用第 6蛇数、7 方案。

一是越、為什么會有1px問題

要處理這個問題耳舅,必須先補充一個知識點,就是設備的 物理像素[設備像素] & 邏輯像素[CSS像素]英妓;

  • 物理像素:
    移動設備出廠時挽放,不同設備自帶的不同像素绍赛,也稱硬件像素蔓纠;

  • 邏輯像素:
    即css中記錄的像素。

在開發(fā)中吗蚌,為什么移動端CSS里面寫了1px腿倚,實際上看起來比1px粗;了解設備物理像素和邏輯像素的同學應該很容易理解蚯妇,其實這兩個px的含義其實是不一樣的敷燎,UI設計師要求的1px是指設備的物理像素1px暂筝,而CSS里記錄的像素是邏輯像素,它們之間存在一個比例關系硬贯,通郴澜螅可以用 javascript 中的 window.devicePixelRatio 來獲取,也可以用媒體查詢的 -webkit-min-device-pixel-ratio 來獲取饭豹。當然鸵赖,比例多少與設備相關。

在手機上border無法達到我們想要的效果拄衰。這是因為 devicePixelRatio 特性導致它褪,iPhone的 devicePixelRatio==2,而 border-width: 1px; 描述的是設備獨立像素翘悉,所以茫打,border被放大到物理像素2px顯示,在iPhone上就顯得較粗妖混。

二老赤、解決方案

1、 媒體查詢利用設備像素比縮放制市,設置小數(shù)像素诗越;

優(yōu)點:簡單,好理解
缺點:兼容性差息堂,目前之余IOS8+才支持嚷狞,在IOS7及其以下、安卓系統(tǒng)都是顯示0px荣堰。

  • IOS8+下已經(jīng)支持帶小數(shù)的px值床未,media query 對應 devicePixelRatio 有個查詢值 -webkit-min-device-pixel-ratio;

  • 1.)css可以寫成這樣:

.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
    .border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
    .border { border: 0.333333px solid #999 }
}
  • 2.)js 可以寫成這樣:
<body><div id="main" style="border: 1px solid #000000;"></div></body>
<script type="text/javascript">
    if (window.devicePixelRatio && devicePixelRatio >= 2) {
        var main = document.getElementById('main');
        main.style.border = '.5px solid #000000';
    }
</script>

二者任選其一振坚;

2薇搁、設置 border-image 方案

缺點:需要制作圖片,圓角可能出現(xiàn)模糊

.border-image-1px {
    border-width: 1px 0px;
    -webkit-border-image: url("border.png") 2 0 stretch;
    border-image: url("border.png") 2 0 stretch;
}
  • border-width:指定邊框的寬度渡八,可以設定四個值啃洋,分別為上右下左border-width: top right bottom left。
  • border-image:該例意為:距離圖片上方2px(屬性值上沒有單位)裁剪邊框圖片作為上邊框屎鳍,下方2px裁剪作為下邊框宏娄。距離左右0像素裁剪圖片即沒有邊框,以拉伸方式展示逮壁。

3孵坚、background-image 漸變實現(xiàn)

除了使用圖片外,當然也能使用純css來實現(xiàn),百度糯米團就是采用的這種方案卖宠。
缺點:因為每個邊框都是線性漸變顏色實現(xiàn)巍杈,因此無法實現(xiàn)圓角。

.border {
      background-image:linear-gradient(180deg, red, red 50%, transparent 50%),
      linear-gradient(270deg, red, red 50%, transparent 50%),
      linear-gradient(0deg, red, red 50%, transparent 50%),
      linear-gradient(90deg, red, red 50%, transparent 50%);
      background-size: 100% 1px,1px 100% ,100% 1px, 1px 100%;
      background-repeat: no-repeat;
      background-position: top, right top,  bottom, left top;
      padding: 10px;
}
  • 原理:將原本1個物理像素的邊框大小利用線性漸變分割成幾個部分(百分比控制)扛伍,實現(xiàn)小于1像素效果筷畦。

  • linear-gradient:指定線性漸變,接受大于等于3個參數(shù)刺洒,第一個為漸變旋轉(zhuǎn)角度汁咏,第二個開始為漸變的顏色和到哪個位置(百分比)全部變?yōu)樵擃伾摾又凶髅模谝痪渚褪侨撂玻瑵u變方向旋轉(zhuǎn)180度,即從上往下(默認為0度從下往上)纸泡,從紅色開始漸變漂问,到50%的位置還是紅色,再漸變?yōu)槔^承父元素顏色女揭。

4蚤假、box-shadow

利用陰影也可以實現(xiàn),優(yōu)點是沒有圓角問題吧兔,缺點是顏色不好控制

div {
    -webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);
}
  • box-shadow屬性的用法:box-shadow: h-shadow v-shadow [blur] [spread] [color] [inset]

參數(shù)分別表示: 水平陰影位置磷仰,垂直陰影位置,模糊距離境蔼, 陰影尺寸灶平,陰影顏色,將外部陰影改為內(nèi)部陰影箍土,后四個可選逢享。該例中為何將陰影尺寸設置為負數(shù)?設置成-1px 是為了讓陰影尺寸稍小于div元素尺寸吴藻,這樣左右兩邊的陰影就不會暴露出來瞒爬,實現(xiàn)只有底部一邊有陰影的效果。從而實現(xiàn)分割線效果(單邊邊框)沟堡。

5侧但、viewport + rem

該方案是對上述方案的優(yōu)化,整體思路就是利用viewport + rem + js 動態(tài)的修改頁面的縮放比例航罗,實現(xiàn)小于1像素的顯示禀横。
缺點:以為縮放涉及全局的rem單位,比較適合新項目伤哺,對于老項目可能要涉及到比較多的改動燕侠。

在頁面初始化時者祖,在頭部引入原始默認狀態(tài)如下:

<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

接下來的任務就是js的動態(tài)修改縮放比 以及 實現(xiàn)rem根元素字體大小的設置立莉。

var viewport = document.querySelector("meta[name=viewport]")
if (window.devicePixelRatio == 1) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
} 
if (window.devicePixelRatio == 2) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
} 
if (window.devicePixelRatio == 3) {
    viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
} 
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;

6绢彤、transform: scale(0.5) 方案 - 推薦: 很靈活

  • 1.) 設置height: 1px,根據(jù)媒體查詢結(jié)合transform縮放為相應尺寸蜓耻。
div {
    height:1px;
    background:#000;
    -webkit-transform: scaleY(0.5);
    -webkit-transform-origin:0 0;
    overflow: hidden;
}
  • 2.) 用::after和::befor,設置border-bottom:1px solid #000,然后在縮放-webkit-transform: scaleY(0.5);可以實現(xiàn)兩根邊線的需求
div::after{
    content:'';width:100%;
    border-bottom:1px solid #000;
    transform: scaleY(0.5);
}
  • 3.) 用::after設置border:1px solid #000; width:200%; height:200%,然后再縮放scaleY(0.5); 優(yōu)點可以實現(xiàn)圓角茫舶,京東就是這么實現(xiàn)的,缺點是按鈕添加active比較麻煩刹淌。
.div::after {
    content: '';
    width: 200%;
    height: 200%;
    position: absolute;
    top: 0;
    left: 0;
    border: 1px solid #bfbfbf;
    border-radius: 4px;
    -webkit-transform: scale(0.5,0.5);
    transform: scale(0.5,0.5);
    -webkit-transform-origin: top left;
}

7饶氏、媒體查詢 + transfrom 對方案1的優(yōu)化

/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.5);
        transform: scaleY(0.5);
    }
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
    .border-bottom::after {
        -webkit-transform: scaleY(0.33);
        transform: scaleY(0.33);
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市有勾,隨后出現(xiàn)的幾起案子疹启,更是在濱河造成了極大的恐慌,老刑警劉巖蔼卡,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喊崖,死亡現(xiàn)場離奇詭異,居然都是意外死亡雇逞,警方通過查閱死者的電腦和手機荤懂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塘砸,“玉大人节仿,你說我怎么就攤上這事〉羰撸” “怎么了廊宪?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長女轿。 經(jīng)常有香客問我挤忙,道長,這世上最難降的妖魔是什么谈喳? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任册烈,我火速辦了婚禮,結(jié)果婚禮上婿禽,老公的妹妹穿的比我還像新娘赏僧。我一直安慰自己,他們只是感情好扭倾,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布淀零。 她就那樣靜靜地躺著,像睡著了一般膛壹。 火紅的嫁衣襯著肌膚如雪驾中。 梳的紋絲不亂的頭發(fā)上唉堪,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音肩民,去河邊找鬼唠亚。 笑死,一個胖子當著我的面吹牛持痰,可吹牛的內(nèi)容都是我干的灶搜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼工窍,長吁一口氣:“原來是場噩夢啊……” “哼割卖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起患雏,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤鹏溯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后淹仑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丙挽,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年攻人,在試婚紗的時候發(fā)現(xiàn)自己被綠了取试。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡怀吻,死狀恐怖瞬浓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蓬坡,我是刑警寧澤猿棉,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站屑咳,受9級特大地震影響萨赁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兆龙,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一杖爽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧紫皇,春花似錦慰安、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至铃剔,卻和暖如春撒桨,著一層夾襖步出監(jiān)牢的瞬間查刻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工凤类, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穗泵,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓踱蠢,卻偏偏與公主長得像火欧,于是被迫代替她去往敵國和親棋电。 傳聞我的和親對象是個殘疾皇子茎截,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348