<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何解決移動(dòng)端 Retina 屏 1px 像素問題 ?

          共 7071字,需瀏覽 15分鐘

           ·

          2021-09-05 22:58

          點(diǎn)擊上方 三分鐘學(xué)前端,關(guān)注公眾號(hào)

          回復(fù)交流,加入前端編程面試算法每日一題群


          面試官也在看的前端面試資料

          什么導(dǎo)致了 1px 問題?

          在移動(dòng)端 Web 開發(fā)中,UI 設(shè)計(jì)稿中設(shè)置邊框?yàn)?1 像素,前端在開發(fā)過程中如果出現(xiàn) border:1px ,測(cè)試會(huì)發(fā)現(xiàn)在 Retina 屏機(jī)型中,1px 會(huì)比較粗,即是較經(jīng)典的移動(dòng)端 1px 像素問題。

          以 iphone6 為例,iphone6 的屏幕寬度為 375px ,設(shè)計(jì)師做的視覺稿一般是750px ,也就是 2x ,這個(gè)時(shí)候設(shè)計(jì)師在視覺稿上畫了 1px 的邊框,于是你就寫了 border:1px ,so...1px邊框問題產(chǎn)生了。

          對(duì)設(shè)計(jì)師來說它的 1px 是相對(duì)于 750px 的(物理像素),對(duì)你來說你的 1px 是相對(duì)于 375px 的(css像素),實(shí)際上你應(yīng)該是 border:0.5px 。

          如何解決?

          方案 優(yōu)點(diǎn) 缺點(diǎn)
          0.5px實(shí)現(xiàn) 代碼簡(jiǎn)單,使用css即可 IOS及Android老設(shè)備不支持
          border-image實(shí)現(xiàn) 兼容目前所有機(jī)型 修改顏色不方便
          viewport + rem 實(shí)現(xiàn) 一套代碼,所有頁面 和0.5px一樣,機(jī)型不兼容
          偽元素 + transform實(shí)現(xiàn) 兼容所有機(jī)型 不支持圓角
          box-shadow模擬邊框?qū)崿F(xiàn) 兼容所有機(jī)型 box-shadow不在盒子模型,需要注意預(yù)留位置
          svg 實(shí)現(xiàn) 實(shí)現(xiàn)簡(jiǎn)單,可以實(shí)現(xiàn)圓角 需要學(xué)習(xí) svg 語法

          0.5px 實(shí)現(xiàn)

          .border-1px { border1px solid #999 }
          @media screen and (-webkit-min-device-pixel-ratio: 2) {
              .border-1px { border0.5px solid #999 }
          }
          /* dpr=2 和 dpr=3 情況下 border 相差無幾,下面代碼可以省略*/
          @media screen and (-webkit-min-device-pixel-ratio: 3) {
              .border-1px { border0.333333px solid #999 }
          }

          但在 IOS7 及以下和 Android 等其他系統(tǒng)里,0.5px 將會(huì)被顯示為 0px 。所以我們需要通過 JS 檢測(cè)瀏覽器能否處理 0.5px 的邊框

          if (window.devicePixelRatio && devicePixelRatio >= 2) {
            var testElem = document.createElement('div');
            testElem.style.border = '.5px solid transparent';
            document.body.appendChild(testElem);
          }
          if (testElem.offsetHeight == 1) {
            document.querySelector('html').classList.add('hairlines');
          }
            document.body.removeChild(testElem);
          }
          • 優(yōu)點(diǎn):簡(jiǎn)單,沒有副作用
          • 缺點(diǎn):支持 iOS 8+,安卓待兼容

          使用 border-image 實(shí)現(xiàn)

          基于 media 查詢判斷不同的設(shè)備像素比給定不同的 border-image

          .border-1px{
              border-bottom1px solid #000;
          }
          @media only screen and (-webkit-min-device-pixel-ratio:2){
              .border_1px{
                  border-bottom: none;
                  border-width0 0 1px 0;
                  border-imageurl(../img/1pxline.png) 0 0 2 0 stretch;
              }
          }

          缺點(diǎn):更換顏色需要更換圖片,圓角模糊

          viewport + rem 實(shí)現(xiàn)

          通過設(shè)置縮放,讓 CSS 像素等于真正的物理像素。

          const scale = 1 / window.devicePixelRatio;
          const viewport = document.querySelector('meta[name="viewport"]');
          if (!viewport) {
              viewport = document.createElement('meta');
              viewport.setAttribute('name''viewport');
              window.document.head.appendChild(viewport);
          }

          viewport.setAttribute('content''width=device-width,user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale);

          // 設(shè)置根字體大小
          var docEl = document.documentElement; 
          var fontsize = 10 * (docEl.clientWidth / 320) + 'px'
          docEl.style.fontSize = fontsize;

          // 在CSS中用rem單位就行了

          缺點(diǎn):

          • 通過 JS 對(duì)文檔進(jìn)行修改,所以性能上有一定影響
          • 會(huì)對(duì)項(xiàng)目中所有使用 rem 單位的對(duì)象進(jìn)行影響。如果是老項(xiàng)目,則會(huì)全部更改 css 樣式(不適合老項(xiàng)目改造)

          偽元素 + transform 實(shí)現(xiàn)

          為什么用偽元素? 因?yàn)閭卧?nbsp;::after 或 ::before 是獨(dú)立于當(dāng)前元素,可以單獨(dú)對(duì)其縮放而不影響元素本身的縮放

          基于 media 查詢判斷不同的設(shè)備像素比對(duì)線條進(jìn)行縮放:

          .border-1px:before{
              content'';
              position: absolute;
              top0;
              height1px;
              width100%;
              background-color#999;
              transform-origin50% 0%;
          }
          @media only screen and (-webkit-min-device-pixel-ratio:2){
              .border-1px:before{
                  transformscaleY(0.5);
              }
          }
          @media only screen and (-webkit-min-device-pixel-ratio:3){
              .border-1px:before{
                  transformscaleY(0.33);
              }
          }

          注意如果需要滿足圓角,需要給偽類也加上 border-radius

          優(yōu)點(diǎn):兼容性好,無副作用,推薦使用

          box-shadow 模擬邊框?qū)崿F(xiàn)

          box-shadow: 0  -1px 1px -1px #999
                      1px  0  1px -1px #999
                      0  1px  1px -1px #999
                      -1px 0  1px -1px #999;

          缺點(diǎn):邊框有陰影,顏色淺,同樣也有兼容性問題,Safari 不支持 1px 以下的 box-shadow。

          svg 實(shí)現(xiàn)

          因?yàn)?nbsp;svg 是矢量圖形,它的 1px 對(duì)應(yīng)的物理像素就是 1px

          可以搭配 PostCSS 的 postcss-write-svg 使用:

          @svg border-1px { 
            height: 2px
            @rect { 
              fillvar(--colorblack); 
              width: 100%; 
              height: 50%; 
              } 
            } 
          .svg { 
              border1px solid transparent; 
              border-imagesvg(border_1px param(--color #00b1ff)) 2 2 stretch; 
          }

          編譯后:

          .svg { border1px solid transparent; border-imageurl("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E"2 2 stretch; }
          • 優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,可以實(shí)現(xiàn)圓角,
          • 缺點(diǎn):需要學(xué)習(xí) svg 語法

          總結(jié)

          綜上,推薦使用:

          • 偽元素 + transform 實(shí)現(xiàn)
          • svg 實(shí)現(xiàn)
          • 新項(xiàng)目可以嘗試使用 viewport 方案

          解決移動(dòng)端 Retina 屏 1px 像素問題

          來自:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/513

          最后

          歡迎關(guān)注「三分鐘學(xué)前端」,回復(fù)「交流」自動(dòng)加入前端三分鐘進(jìn)階群,每日一道編程算法面試題(含解答),助力你成為更優(yōu)秀的前端開發(fā)!

          號(hào)內(nèi)回復(fù):

          網(wǎng)絡(luò)」,自動(dòng)獲取三分鐘學(xué)前端網(wǎng)絡(luò)篇小書(90+頁)
          JS」,自動(dòng)獲取三分鐘學(xué)前端 JS 篇小書(120+頁)
          算法」,自動(dòng)獲取 github 2.9k+ 的前端算法小書
          面試」,自動(dòng)獲取 github 23.2k+ 的前端面試小書
          簡(jiǎn)歷」,自動(dòng)獲取程序員系列的 120 套模版
          》》面試官也在看的前端面試資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的


          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久国产视屏 | 日韩午夜福利无码一区不卡 | www.夜夜 | 日韩高清无码本道 | 97一区二区 |