在 retina 屏中實現 1px border 效果

騰訊雲技術社區-掘金主頁持續爲你們呈現雲計算技術文章,歡迎你們關注!css


做者:linkhtml

街景wap官網中有在視網膜屏幕中實現1px border的需求.
首先,來看下面視覺給的輸出圖中的border:
前端

從上面的視覺圖能夠看到,border是一根很是細的線。這篇文章將說明如何使用border-image實如今視網膜屏中1px的border效果。android

注:由於硬件條件的限制,設備像素比(devicePixelRatio)爲1的非視網膜屏手機沒法達到這樣的效果ios

首先準備一張符合你要求的border-image:css3

一般手機端的頁面設計稿都是放大一倍的,如:爲適應iphone retina,設計稿會設計成640*960的分辨率,圖片按照2倍大小切出來,在手機端看着就不會虛化,很是清晰。
一樣,在使用border-image時,將border設計爲物理1px,以下:git

樣式設置:github

.border-image-1px {
    border-width: 0 0 1px 0;
    -webkit-border-image: url(linenew.png) 0 0 2 0 stretch;
    border-image: url(linenew.png) 0 0 2 0 stretch;
}複製代碼

上文是把border設置在邊框的底部,因此使用的圖片是2px高,上部的1px顏色爲透明,下部的1px使用視覺規定的border的顏色。若是邊框底部和頂部同時須要border,可使用下面的border-image:web

樣式設置:sass

.border-image-1px {
    border-width: 1px 0;
    -webkit-border-image: url(linenew.png) 2 0 stretch;
    border-image: url(linenew.png) 2 0 stretch;
}複製代碼

到目前爲止,咱們已經能在iphone上展示1px border的效果了。可是咱們發現這樣的方法在非視網膜屏上會出現border顯示不出來的現象,因而使用Media Query作了一些兼容,樣式設置以下:

.border-image-1px {
    border-bottom: 1px solid #666;
} 

@media only screen and (-webkit-min-device-pixel-ratio: 2) {
    .border-image-1px {
        border-bottom: none;
        border-width: 0 0 1px 0;
        -webkit-border-image: url(../img/linenew.png) 0 0 2 0 stretch;
        border-image: url(../img/linenew.png) 0 0 2 0 stretch;
    }
}複製代碼

參考文檔:
github.com/AlloyTeam/M…
css-tricks.com/snippets/cs…

下面介紹一下其餘方法:

  • 設置viewport
    直接按照設計師提供的640px寬的設計稿來重構,而後經過控制viewport的initial-scale值爲0.5進行縮放,這種方案在ios下能夠完美運行(淘寶就是這麼作的),可是因爲android下不支持initial-scale,因此這個方案不適用於android。
<meta name="viewport" content="initial-scale=0.5,user-scalable=no"/>複製代碼
  • background-image
    跟border-image的方法同樣,你要先準備一張符合你要求的圖片:

此例是準備將border設置在底部
樣式設置:

.background-image-1px {
    background: url(../img/line.png) repeat-x left bottom;
    -webkit-background-size: 100% 1px;
    background-size: 100% 1px;
}複製代碼
  • box-shadow
.box-shadow-1px {
    box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}複製代碼

使用box-shadow都會讓線有陰影,甚至顏色變淺。可是使用box-shadow與使用border相似,代碼量少,使用方便,並且能夠設置圓角矩形,在精細度要求不高的狀況下能夠嘗試使用這種方案。

  • 漸變背景
    與background-image方案相似,只是將圖片替換爲css3漸變。
    樣式設置:
.background-gradient-1px{
   background: -webkit-gradient(linear, left top, left bottom, color-stop(.5, transparent), color-stop(.5, #c8c7cc), to(#c8c7cc)) left bottom repeat-x;
   background-size: 100% 1px;
}複製代碼

該方案不能知足1px圓角矩形。

  • 縮放
    邊框由一個元素來承載,將這個元素的高度(或寬度)設置爲1px,而後再將該元素縮放1倍。
    樣式設置:
.scale-1px{
   position: relative;
}
.scale-1px:after{
   content:"";
   position: absolute;
   bottom:0px;
   left:0px;
   right:0px;
   border-bottom:1px solid #c8c7cc;
   -webkit-transform:scaleY(.5);
   -webkit-transform-origin:0 0;
}複製代碼
  • 據說Firefox和Safari8已經支持0.5px的單位了,代碼能夠像下面這樣寫:
div{
   border:1px solid black;
}

@media (-webkit-min-device-pixel-ratio: 2){
 div{
    border-width:0.5px;
 }
}複製代碼

不過0.5px這個單位有點過於顛覆前端開發的認識了twitter上有位哥們已經被震驚的不知所云

  • 基於border-imagetransform使用Sass的線下解決方案:
    Mixin:sass中使用@mixin聲明混合,能夠傳遞參數,參數名以$符號開始,多個參數以逗號分開,也能夠給參數設置默認值。聲明的@mixin經過@include來調用。
  1. 基於border-image:

_onepx.scss:

@mixin onepx($selector, $position: bottom, $color: #666, $onepxImgDirname: './img/linenew.png') {
  #{$selector} {
    border-#{$position}: 1px solid $color;
  }

  @media only screen and (-webkit-min-device-pixel-ratio:2) {
    #{$selector} {
      border-#{$position}: none;
      @if $position == 'bottom' {
        border-width: 0 0 1px 0;
        -webkit-border-image: url($onepxImgDirname) 0 0 2 0 stretch;
        border-image: url($onepxImgDirname) 0 0 2 0 stretch;
      } @else if $position == 'top' {
        border-width: 1px 0 0 0;
        -webkit-border-image: url($onepxImgDirname) 2 0 0 0 stretch;
        border-image: url($onepxImgDirname) 2 0 0 0 stretch;
      } @else if $position == 'right' {
        border-width: 0 1px 0 0;
        -webkit-border-image: url($onepxImgDirname) 0 2 0 0 stretch;
        border-image: url($onepxImgDirname) 0 2 0 0 stretch;
      } @else if $position == 'left' {
        border-width: 0 0 0 1px;
        -webkit-border-image: url($onepxImgDirname) 0 0 0 2 stretch;
        border-image: url($onepxImgDirname) 0 0 0 2 stretch;
      }  
    }
  }
}複製代碼

test.scss:

@import "onepx";

.container {
  @include onepx('.myonepx', 'top', '#666', './img/linenew.png');
}

@include onepx('.border-top', 'top');
@include onepx('.border-bottom');複製代碼

執行bat文件:

sass --scss --style expanded test.scss test.css

生成css代碼:

.container .myonepx {
  border-top: 1px solid "#666";
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .container .myonepx {
    border-top: none;
    border-width: 1px 0 0 0;
    -webkit-border-image: url("./img/linenew.png") 2 0 0 0 stretch;
    border-image: url("./img/linenew.png") 2 0 0 0 stretch;
  }
}

.border-top {
  border-top: 1px solid #666666;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border-top {
    border-top: none;
    border-width: 1px 0 0 0;
    -webkit-border-image: url("./img/linenew.png") 2 0 0 0 stretch;
    border-image: url("./img/linenew.png") 2 0 0 0 stretch;
  }
}
.border-bottom {
  border-bottom: 1px solid #666666;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border-bottom {
    border-bottom: none;
    border-width: 0 0 1px 0;
    -webkit-border-image: url("./img/linenew.png") 0 0 2 0 stretch;
    border-image: url("./img/linenew.png") 0 0 2 0 stretch;
  }
}複製代碼
  1. 基於transform的縮放:

_onpx.scss

@mixin _prefixDpr($selector, $position: 'top', $pseudo: 'before', $dpr: '2') {
  @media only screen and (-webkit-min-device-pixel-ratio:$dpr) {
    @if $dpr == '1.5' {
      #{$selector}:#{$pseudo} {
        -webkit-transform: scaleY(.7);
        transform: scaleY(.7);
        @if $position == 'top' {
          -webkit-transform-origin: left top;
        } @else if $position == 'bottom' {
          -webkit-transform-origin: left bottom;
        }
      }
    } @else if $dpr == '2' {
      #{$selector}:#{$pseudo} {
        -webkit-transform: scaleY(.5);
        transform: scaleY(.5);
        @if $position == 'top' {
          -webkit-transform-origin: left top;
        } @else if $position == 'bottom' {
          -webkit-transform-origin: left bottom;
        }
      }
    } @else if $dpr == '3' {
      #{$selector}:#{$pseudo} {
        -webkit-transform: scaleY(.3);
        transform: scaleY(.3);
        @if $position == 'top' {
          -webkit-transform-origin: left top;
        } @else if $position == 'bottom' {
          -webkit-transform-origin: left bottom;
        }
      }
    }
  }
}

@mixin onepx($selector, $position: 'top',$pseudo: 'before', $color: #666) {
    #{$selector}:#{$pseudo} {
      content: ' ';
      display: block;
      border-top: 1px solid $color;
      position: absolute;
      left: 0;
      right: 0;
    }
    #{$selector} {
        position: relative;
        &:#{$pseudo} {
          @if #{$position} == 'top'{
            top: 0;
          } @else if #{$position} == 'bottom' {
            bottom: 0;
          }
        }
    }
    @include _prefixDpr($selector, $position, $pseudo, '1.5');
    @include _prefixDpr($selector, $position, $pseudo, '2');
    @include _prefixDpr($selector, $position, $pseudo, '3');

}複製代碼

test.scss

@import "onepx";

.container {
  @include onepx('.myonepx');
}

@include onepx('.hello', 'bottom', 'after', '#777');複製代碼

執行bat文件

sass --scss --style expanded test.scss test.css
生成css代碼:

.container .myonepx:before {
  content: ' ';
  display: block;
  border-top: 1px solid #666666;
  position: absolute;
  left: 0;
  right: 0;
}
.container .myonepx {
  position: relative;
}
.container .myonepx:before {
  top: 0;
}
@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {
  .container .myonepx:before {
    -webkit-transform: scaleY(0.7);
    transform: scaleY(0.7);
    -webkit-transform-origin: left top;
  }
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .container .myonepx:before {
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
    -webkit-transform-origin: left top;
  }
}
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
  .container .myonepx:before {
    -webkit-transform: scaleY(0.3);
    transform: scaleY(0.3);
    -webkit-transform-origin: left top;
  }
}

.hello:after {
  content: ' ';
  display: block;
  border-top: 1px solid "#777";
  position: absolute;
  left: 0;
  right: 0;
}

.hello {
  position: relative;
}
.hello:after {
  top: 0;
}

@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {
  .hello:after {
    -webkit-transform: scaleY(0.7);
    transform: scaleY(0.7);
    -webkit-transform-origin: left bottom;
  }
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .hello:after {
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
    -webkit-transform-origin: left bottom;
  }
}
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
  .hello:after {
    -webkit-transform: scaleY(0.3);
    transform: scaleY(0.3);
    -webkit-transform-origin: left bottom;
  }
}複製代碼

好處:可使用習慣的sass寫1px的實現方案,而且支持傳參,更加靈活。

參考:
www.topcss.org/?p=769
謝謝導師donaldyang的指導。

相關推薦
圖片流量節省大殺器:基於CDN的sharpP自適應圖片技術實踐
萬象優圖CI
頁面性能優化的利器 — Timeline


此文已由做者受權騰訊雲技術社區發佈,轉載請註明文章出處
原文連接:www.qcloud.com/community/a…
獲取更多騰訊海量技術實踐乾貨,歡迎你們前往騰訊雲技術社區

相關文章
相關標籤/搜索