移動端1px解決方案

前言

移動端web項目愈來愈多,設計師對於UI的要求也愈來愈高,好比1px 的邊框。在高清屏下,移動端的1px 會很粗。javascript

好比,這個是假的1像素php

這個是真的1像素css

1、產生緣由

那麼爲何會產生這個問題呢?主要是跟一個東西有關,DPR(devicePixelRatio) 設備像素比,它是默認縮放爲100%的狀況下,設備像素和CSS像素的比值。html

window.devicePixelRatio=物理像素 /CSS像素 
複製代碼

目前主流的屏幕DPR=2 (iPhone 8),或者3 (iPhone 8 Plus)。拿2倍屏來講,設備的物理像素要實現1像素,而DPR=2,因此css 像素只能是 0.5。通常設計稿是按照750來設計的,它上面的1px是以750來參照的,而咱們寫css樣式是以設備375爲參照的,因此咱們應該寫的0.5px就行了啊! 試過了就知道,iOS 8+系統支持,安卓系統不支持。java

2、解決方案

一、WWDC對iOS統給出的方案

推薦指數:**

在 WWDC大會上,給出來了1px方案,當寫 0.5px的時候,就會顯示一個物理像素寬度的 border,而不是一個css像素的 border。 因此在iOS下,你能夠這樣寫。css3

border:0.5px solid #E5E5E5
複製代碼

可能你會問爲何在3倍屏下,不是0.3333px 這樣的?通過我測試,在Chrome上模擬iPhone 8Plus,發現0.46-顯示不出來。web

總結:bash

  • 優勢:簡單,沒有反作用
  • 缺點:支持iOS 8+,不支持安卓。後期安卓follow就行了。

二、使用邊框圖片

推薦指數:**

border: 1px solid transparent;
    border-image: url('./../../image/96.jpg') 2 repeat;
複製代碼

圖片本身隨便截圖的,建議本身作一張圖片。移動端web

圖片的顏色就是此後border的顏色測試

這個方法在W3CPlus 上的例子講的很是細緻 www.w3cplus.com/content/css…

總結:

  • 優勢:沒有反作用
  • 缺點:border顏色變了就得從新制做圖片;圓角會比較模糊。

三、使用box-shadow實現

推薦指數:***

先複習一下box-shadow,看一下MDN 上的這篇就夠了 developer.mozilla.org/zh-CN/docs/…

再看一下效果

代碼是怎樣實現的呢?

box-shadow: 0  -1px 1px -1px #e5e5e5, //上邊線
			1px  0  1px -1px #e5e5e5, //右邊線
			0  1px  1px -1px #e5e5e5, //下邊線
			-1px 0  1px -1px #e5e5e5; //左邊線
複製代碼

前面兩個值 x,y 主要控制顯示哪條邊,後面兩值控制的是陰影半徑、擴展半徑。 其實方法能夠到這個地址線上嘗試一下

總結

  • 優勢:使用簡單,圓角也能夠實現
  • 缺點:模擬的實現方法,仔細看誰看不出來這是陰影不是邊框。

四、使用僞元素

推薦指數:****

這個方法是我使用最多的,作出來的效果也是很是棒的,直接上代碼。

1 條border

.setOnePx{
    position: relative;
    &::after{
      position: absolute;
      content: '';
      background-color: #e5e5e5;
      display: block;
      width: 100%;
      height: 1px; /*no*/
      transform: scale(1, 0.5);
      top: 0;
      left: 0;
    }
  }
複製代碼

能夠看到,將僞元素設置相對定位,而且和父元素的左上角對其,將width 設置100%,height設置爲1px,而後進行在Y方向縮小0.5倍

4 條border

.setBorderAll{
       position: relative;
         &:after{
             content:" ";
             position:absolute;
             top: 0;
             left: 0;
             width: 200%;
             height: 200%;
             transform: scale(0.5);
             transform-origin: left top;
             box-sizing: border-box;
             border: 1px solid #E5E5E5;
             border-radius: 4px;
        }
      }
複製代碼

一樣爲僞元素設置相對定位,而且和父元素左上角對其。將僞元素的長和寬先放大2倍,而後再設置一個邊框,以左上角爲中心,縮放到原來的0.5倍

總結:

  • 優勢:全機型兼容,實現了真正的1px,並且能夠圓角。
  • 缺點:暫用了after 僞元素,可能影響清除浮動。

五、設置viewport的scale值

推薦指數:*****

這個解決方案是利用viewport+rem+js 實現的。 參考了網上的一個例子 移動端1像素邊框問題的解決方案,本身手動實現了一下。

效果不錯。 上代碼

<html>
	<head>
		<title>1px question</title>
		<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">		
		<style>
			html {
				font-size: 1px;
			}			
			* {
				padding: 0;
				margin: 0;
			}
			.top_b {
				border-bottom: 1px solid #E5E5E5;
			}
			
			.a,.b {
                        box-sizing: border-box;
				margin-top: 1rem;
				padding: 1rem;				
				font-size: 1.4rem;
			}
			
			.a {
				width: 100%;
			}
			
			.b {
				background: #f5f5f5;
				width: 100%;
			}
		</style>
		<script>
			var viewport = document.querySelector("meta[name=viewport]");
			//下面是根據設備像素設置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.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
			}
			var docEl = document.documentElement;
			var fontsize = 32* (docEl.clientWidth / 750) + 'px';
			docEl.style.fontSize = fontsize;
		</script>
	</head>
	<body>
		<div class="top_b a">下面的底邊寬度是虛擬1像素的</div>
		<div class="b">上面的邊框寬度是虛擬1像素的</div>
	</body>
</html>
複製代碼

總結

  • 優勢:全機型兼容,直接寫1px不能再方便
  • 缺點:適用於新的項目,老項目可能改動大

3、踩過坑

一部血淚史。。。。征服不了UI,只能征服本身。

一、使用僞元素方法,僞類裏面再設置僞元素,能夠選擇到嗎?

看圖,須要改中間的豎線

上代碼

&:nth-child(2){
        //border-color: #e5e5e5 !important;
          border: 0;
        position: relative;
        &:after{
          position: absolute;
          content: '';
          background-color: #e5e5e5;
          display: block;
          width: 100%;
          height: 1px; /*no*/
          transform: scale(1, 0.5);
          top: 0;
        }
      }
複製代碼

然而上面代碼展現出來的樣式是這樣的

爲何中間的豎線沒有了?!最初我覺得在僞類下面,再寫僞元素after,可能會拿不到。

看到這裏發現,是有after僞元素的,可是好像位置不對,跑到上面去了。我是想要豎線的,到底什麼緣由呢?最後在安哥的找了一種方法解決了這個問題,才明白其中的真相。

原來是個人width 和 height 設置的有問題,對於豎線,應該是width =1px,height=100%,而後再縮放 X 方向0.5倍,這樣豎線就出來了;一樣,設置水平線,應該是width=100%,height=1px,而後再縮放Y方向0.5倍

知道了緣由,不再擔憂寫錯了。

&:nth-child(2){
        position: relative;
        &:after{
          position: absolute;
          content: '';
          top: 0;
          left: 0;
          width: 1px;
          height: 100%;
          transform: scaleX(0.5);
          background: #e5e5e5;
          transform-origin: 0 0;
        }
      }
複製代碼

這樣是能夠的,

&:nth-child(2){
        position: relative;
        &:after{
          content:" ";
          position:absolute;
          top: 0;
          left: 0;
          width: 200%;
          height: 200%;
          transform: scale(0.5);
          transform-origin: left top;
          box-sizing: border-box;
          border-left: 1px solid #E5E5E5;
        }
      }
複製代碼

這樣也能夠的。

二、爲何仍是拿不到僞元素

我覺得知道了上面的方法就能夠快快樂樂的寫1像素 border 了,然而立刻又懷疑本身了。

上面這個輸入框的1像素,須要的全部的border都是1px,我使用了寬高放大200%後再縮小 0.5倍的方法。

這就奇怪了,一樣的方法在別的地方都有效的,爲何在這裏不顯示了。找了很久,最後找到這篇文章 使用 CSS 僞元素須要注意的 ,而後發現:

因此不顯示的緣由找到了, 輸入框Textarea不支持僞元素

沒辦法了,僞元素的方法不能用,只能使用其餘的方法了。

4、總結

總結一下,新項目最好使用的是設置viewport的scale值,這個方法兼容性好,後期寫起來方便。老項目的話,改起來可能比較多,用的比較多的方法就是僞元素+transform的方法。

其餘的背景圖片,陰影的方法畢竟仍是不太靈活,並且兼容性很差。

相關文章
相關標籤/搜索