移動(dòng)端 1px 邊框的問(wèn)題

物理像素[設(shè)備像素] & 邏輯像素[CSS 像素]

背景

拿2倍屏來(lái)說(shuō)环鲤,設(shè)備的物理像素要實(shí)現(xiàn)1像素温数,而DPR=2古徒,所以css 像素只能是 0.5爆雹。一般設(shè)計(jì)稿是按照750來(lái)設(shè)計(jì)的性穿,它上面的1px是以750來(lái)參照的勺三,而我們寫css樣式是以設(shè)備375為參照的,所以我們應(yīng)該寫的0.5px就好了靶柙吗坚! 試過(guò)了就知道,iOS 8+系統(tǒng)支持呆万,安卓系統(tǒng)不支持商源。

在瀏覽器中無(wú)法設(shè)置小于 1px 的邊框 設(shè)置了也不會(huì)生效

為什么 1px 變粗了

設(shè)計(jì)師要求的 1px 是指設(shè)備的物理像素 1px,而 CSS 里記錄的像素是邏輯像素谋减,它們之間存在一個(gè)比例關(guān)系牡彻,可以用 javascript 中的 window.devicePixelRatio 來(lái)獲取。當(dāng)然逃顶,比例多少與設(shè)備相關(guān)讨便。

移動(dòng)端開(kāi)發(fā)常需要在 html 的 header 里添加如下一句:

? <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

設(shè)備像素比 = 物理像素 / css 像素

如何解決

核心思想就是設(shè)置 1px 大小 然后將 1px 縮小為 0.5px 來(lái)展示

  1. 媒體查詢利用設(shè)備像素比縮放充甚,設(shè)置小數(shù)像素

IOS8 下已經(jīng)支持帶小數(shù)的 px 值, media query 對(duì)應(yīng) devicePixelRatio 有個(gè)查詢值-webkit-min-device-pixel-ratio, 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 }
}

【缺點(diǎn)】對(duì)設(shè)備有要求,小數(shù)像素目前兼容性較差霸褒。

  1. transform: scale(0.5) 方案 推薦
  • 設(shè)置 height: 1px伴找,根據(jù)媒體查詢結(jié)合 transform 縮放為相應(yīng)尺寸。
div {
    height:1px;
    background:#000;
    -webkit-transform: scaleY(0.5);
    -webkit-transform-origin:0 0;
    overflow: hidden;
}
  • 用::after 和::befor,設(shè)置 border-bottom:1px solid #000,然后在縮放-webkit-transform: scaleY(0.5);可以實(shí)現(xiàn)兩根邊線的需求
div::after{
    content:'';
    width:100%;
    border-bottom:1px solid #000;
    transform: scaleY(0.5);
}

pixel-border.css 這個(gè)工具庫(kù)就是用來(lái)解決移動(dòng)端 1px 邊框的問(wèn)題废菱,用到的思想和我下面寫的一致

.one-pixel-border::before {
  display: block;
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200%;
  height: 200%;
  border: 1px solid red;
  transform: translate(-50%, -50%) scale(0.5, 0.5);
}

pixel-border.css

/**
 * version:0.0.1
 * https://github.com/JofunLiang/pixel-border
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 */
:root {
  --pixel-border-dpr: 1;
}

@media screen and (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
  :root {
    --pixel-border-dpr: 2;
  }
}

@media screen and (-webkit-min-device-pixel-ratio: 3), (min-resolution: 3dppx) {
  :root {
    --pixel-border-dpr: 3;
  }
}

@media screen and (-webkit-min-device-pixel-ratio: 4), (min-resolution: 4dppx) {
  :root {
    --pixel-border-dpr: 4;
  }
}

[pixel-border],
[pixel-border=true] {
  position: relative;
  border-width: 0;
  box-sizing: border-box;
}

[pixel-border]::before,
[pixel-border=true]::before {
  --scale: calc(1 / var(--pixel-border-dpr));
  --size: calc(var(--pixel-border-dpr) * 100%);
  content: '';
  pointer-events: none;
  display: block;
  box-sizing: inherit;
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--size);
  height: var(--size);
  border: inherit;
  border-width: 1px;
  border-image: inherit;
  border-radius: inherit;
  transform: translate(-50%, -50%) scale(var(--scale), var(--scale));
}
  1. viewport + rem 方案

該方案是對(duì)上述方案的優(yōu)化技矮,整體思路就是利用 viewport + rem + js 動(dòng)態(tài)的修改頁(yè)面的縮放比例,實(shí)現(xiàn)小于 1 像素的顯示殊轴。在頁(yè)面初始化時(shí)衰倦,在頭部引入原始默認(rèn)狀態(tài)如下:

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

接下來(lái)的任務(wù)就是 js 的動(dòng)態(tài)修改縮放比 以及 實(shí)現(xiàn) rem 根元素字體大小的設(shè)置。

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;
// 320指的是我們以寬度為320的設(shè)備作為依據(jù) iPhone 5/SE旁理,這樣設(shè)置的 1rem 就是 20px 為的就是比較好計(jì)算
// 比如說(shuō) iphone 6/7/8的寬度是 375 那么這里我們就可以設(shè)置為 375 然后我們的 1rem 在這個(gè)設(shè)備上就是 20px (CSS像素)但是一般給的
// 設(shè)計(jì)稿都是 物理像素 也就是CSS像素 * 設(shè)備像素比(一般是2)
var fontsize = 20 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;

【缺點(diǎn)】以為縮放涉及全局的 rem 單位樊零,比較適合新項(xiàng)目,對(duì)于老項(xiàng)目可能要涉及到比較多的改動(dòng)孽文。

  1. 在iOS下驻襟,你可以這樣寫
border:0.5px solid #E5E5E5

可能你會(huì)問(wèn)為什么在3倍屏下,不是0.3333px 這樣的芋哭?經(jīng)過(guò)我測(cè)試沉衣,在Chrome上模擬iPhone 8Plus,發(fā)現(xiàn)小于0.46px的時(shí)候是顯示不出來(lái)减牺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末豌习,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拔疚,更是在濱河造成了極大的恐慌肥隆,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稚失,死亡現(xiàn)場(chǎng)離奇詭異巷屿,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)墩虹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)憨琳,“玉大人诫钓,你說(shuō)我怎么就攤上這事「菝” “怎么了菌湃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)遍略。 經(jīng)常有香客問(wèn)我惧所,道長(zhǎng)骤坐,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任下愈,我火速辦了婚禮纽绍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘势似。我一直安慰自己拌夏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布履因。 她就那樣靜靜地躺著障簿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪栅迄。 梳的紋絲不亂的頭發(fā)上站故,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音毅舆,去河邊找鬼丧凤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛洗贰,可吹牛的內(nèi)容都是我干的柿隙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼余掖,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寸爆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起盐欺,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赁豆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后冗美,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體魔种,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年粉洼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了节预。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡属韧,死狀恐怖安拟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宵喂,我是刑警寧澤糠赦,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響拙泽,放射性物質(zhì)發(fā)生泄漏淌山。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一顾瞻、第九天 我趴在偏房一處隱蔽的房頂上張望泼疑。 院中可真熱鬧,春花似錦朋其、人聲如沸王浴。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)氓辣。三九已至,卻和暖如春袱蚓,著一層夾襖步出監(jiān)牢的瞬間钞啸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工喇潘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留体斩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓颖低,卻偏偏與公主長(zhǎng)得像絮吵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子忱屑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容