前言:在移動端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);
}
}