溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

html中移動(dòng)端1px問(wèn)題實(shí)例分析

發(fā)布時(shí)間:2022-04-24 15:54:22 來(lái)源:億速云 閱讀:90 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“html中移動(dòng)端1px問(wèn)題實(shí)例分析”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“html中移動(dòng)端1px問(wèn)題實(shí)例分析”吧!

問(wèn)題

  • 為什么有 1px 這個(gè)問(wèn)題?

  • 實(shí)現(xiàn) 1px 有哪些方法?這些方法分別有哪些優(yōu)缺點(diǎn)?

  • 開(kāi)源項(xiàng)目中使用的哪些解決方案?

  • 如何在項(xiàng)目中處理 1px 的相關(guān)問(wèn)題?

由來(lái)

 基本概念

首先,我們要了解兩個(gè)概念,一個(gè)是 像素(pixel) 可以簡(jiǎn)寫(xiě)為 px ,另外一個(gè)是 設(shè)備像素比(DPR)

像素 :指在由一個(gè)數(shù)字序列表示的圖像中的一個(gè)最小單元,單位是 px,不可再次分割了。

設(shè)備像素比(DPR): 設(shè)備像素比 = 設(shè)備像素 / 設(shè)備獨(dú)立像素。

下面我來(lái)簡(jiǎn)單解釋下幾個(gè)概念

  • CSS 像素 (虛擬像素):指的是 CSS 樣式代碼中使用的邏輯像素,在 CSS 規(guī)范中,長(zhǎng)度單位可以分為兩類(lèi),絕對(duì)單位以及相對(duì)單位。px 是一個(gè)相對(duì)單位,相對(duì)的是設(shè)備像素。

  • 設(shè)備像素 (物理像素):指設(shè)備能控制顯示的最小物理單位,意指顯示器上一個(gè)個(gè)的點(diǎn)。從屏幕在工廠生產(chǎn)出的那天起,它上面設(shè)備像素點(diǎn)就固定不變了,和屏幕尺寸大小有關(guān)。

  • 設(shè)備獨(dú)立像素 (邏輯像素):可以認(rèn)為是計(jì)算機(jī)坐標(biāo)系統(tǒng)中得一個(gè)點(diǎn),這個(gè)點(diǎn)代表一個(gè)可以由程序使用的虛擬像素(比如: CSS 像素),這個(gè)點(diǎn)是沒(méi)有固定大小的,越小越清晰,然后由相關(guān)系統(tǒng)轉(zhuǎn)換為物理像素。 也就是說(shuō),當(dāng)邏輯像素是 1pt 時(shí),在 DPR 為 2 的 設(shè)備上顯示為 2px 的物理像素

 參考數(shù)據(jù)

各種類(lèi)型的 iphone 手機(jī)屏幕設(shè)備的參數(shù)

html中移動(dòng)端1px問(wèn)題實(shí)例分析

注:這里的縮放因子呢,就是 DRP 的值

設(shè)計(jì)稿對(duì)比數(shù)據(jù)

html中移動(dòng)端1px問(wèn)題實(shí)例分析

會(huì)有人好奇,為什么設(shè)計(jì)稿上顯示是 750x1334 呢,這是因?yàn)樵O(shè)計(jì)稿是顯示的 物理像素

而我們 css 中的像素是 邏輯像素 應(yīng)該為 375x 667,在編寫(xiě)代碼時(shí)要將自定義寬度設(shè)置成 375px

html中移動(dòng)端1px問(wèn)題實(shí)例分析

那么此時(shí)設(shè)計(jì)稿上的 1px 寬度實(shí)際代表的 css 參數(shù)應(yīng)該是 0.5px 對(duì)應(yīng)物理像素 1px,那么怎么實(shí)現(xiàn)這個(gè)物理像素為 1px 呢

實(shí)踐

歸根結(jié)底有兩種方案,一種是利用 css 中的 transfrom:scaleY(0.5) ,另一種是設(shè)置 媒體查詢(xún)根據(jù)不同 DPR 縮放

解決方案一

原理

利用 css 的 偽元素 ::after + transfrom 進(jìn)行縮放

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

偽元素大多數(shù)瀏覽器默認(rèn)單引號(hào)也可以使用,和偽類(lèi)一樣形式,而且單引號(hào)兼容性(ie)更好些

實(shí)現(xiàn)

<div class="cell border-1px"> cell <div>

<style>
.cell {
    width: 100px;
    height: 100px;
}
<!--全部邊框-->
.border-1px:after {
    content: '';
    position: absolute;
    box-sizing: border-box;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    border: 1px solid #000;
    border-radius: 4px;
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
    -webkit-transform-origin: top left;
}

<!--單邊框,以上邊框?yàn)槔?->
.border-1px-top:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    border-top: 1px solid red;
    transform: scaleY(.5);
    transform-origin: left top;
}
</style>

解決方案二(升級(jí)方案一)

原理

使用 less 對(duì)公共代碼(方案一)封裝,同時(shí)增加媒體查詢(xún)分別對(duì)不同 DPR 的設(shè)備,進(jìn)行不同的縮放

.border(
    @borderWidth: 1px; 
    @borderStyle: solid; 
    @borderColor: @lignt-gray-color; 
    @borderRadius: 0) {
    position: relative;
    &:before {
        content: '';
        position: absolute;
        width: 98%;
        height: 98%;
        top: 0;
        left: 0;
        transform-origin: left top;
        -webkit-transform-origin: left top;
        box-sizing: border-box;
        pointer-events: none;
    }
    @media (-webkit-min-device-pixel-ratio: 2) {
        &:before {
            width: 200%;
            height: 200%;
            -webkit-transform: scale(.5);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 2.5) {
        &:before {
            width: 250%;
            height: 250%;
            -webkit-transform: scale(.4);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 2.75) {
        &:before {
            width: 275%;
            height: 275%;
            -webkit-transform: scale(1 / 2.75);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 3) {
        &:before {
            width: 300%;
            height: 300%;
            transform: scale(1 / 3);
            -webkit-transform: scale(1 / 3);
        }
    }
    .border-radius(@borderRadius);
    &:before {
        border-width: @borderWidth;
        border-style: @borderStyle;
        border-color: @borderColor;
    }
}

.border-all(
	@borderWidth: 1px; 
	@borderStyle: solid; 
	@borderColor: @lignt-gray-color; 
	@borderRadius: 0) {
    .border(@borderWidth; @borderStyle; @borderColor; @borderRadius);
}

其他方案:

使用圖片:兼容性最好,靈活行最差,不能改變顏色、長(zhǎng)度

使用 viewport 和 rem , js 動(dòng)態(tài)改變 viewport 中 scale 縮放,缺點(diǎn)在于不適用于已有的項(xiàng)目,例如:使用 vh 和 vw 布局的

  <meta name="viewport" id="WebViewport" content="initial-scale=1,    maximum-scale=1, minimum-scale=1, user-scalable=no">

使用 css 漸變 linear-gradient 或者 box-shadow

上述 3 種方案均有致命缺陷暫不推薦使用

兼容性

最后看一下兼容性如何,主要是偽元素、 transform:scale 和 min-device-pixel-ratio 這幾個(gè)關(guān)鍵詞的兼容性

html中移動(dòng)端1px問(wèn)題實(shí)例分析  

開(kāi)源庫(kù)的解決方案

vant 組件庫(kù)

跳去 github 查看相關(guān)代碼

使用 less 寫(xiě)的

.hairline-common() {
  position: absolute;
  box-sizing: border-box;
  content: ' ';
  pointer-events: none;
}

.hairline(@color: @border-color) {
  .hairline-common();

  top: -50%;
  right: -50%;
  bottom: -50%;
  left: -50%;
  border: 0 solid @color;
  transform: scale(0.5);
}

也是采用第一種解決方案

ant-design-mobile 組件庫(kù)

跳去 github 查看相關(guān)代碼

.scale-hairline-common(@color, @top, @right, @bottom, @left) {
  content: '';
  position: absolute;
  background-color: @color;
  display: block;
  z-index: 1;
  top: @top;
  right: @right;
  bottom: @bottom;
  left: @left;
}

.hairline(@direction, @color: @border-color-base) when (@direction = 'top') {
  border-top: 1PX solid @color;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-top: none;

      &::before {
        .scale-hairline-common(@color, 0, auto, auto, 0);
        width: 100%;
        height: 1PX;
        transform-origin: 50% 50%;
        transform: scaleY(0.5);

        @media (min-resolution: 3dppx) {
          transform: scaleY(0.33);
        }
      }
    }
  }
}

.hairline(@direction, @color: @border-color-base) when (@direction = 'right') {
  border-right: 1PX solid @color;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-right: none;

      &::after {
        .scale-hairline-common(@color, 0, 0, auto, auto);
        width: 1PX;
        height: 100%;
        background: @color;
        transform-origin: 100% 50%;
        transform: scaleX(0.5);

        @media (min-resolution: 3dppx) {
          transform: scaleX(0.33);
        }
      }
    }
  }
}
.hairline(@direction, @color: @border-color-base) when (@direction = 'bottom') {
  border-bottom: 1PX solid @color;
  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-bottom: none;
      &::after {
        .scale-hairline-common(@color, auto, auto, 0, 0);
        width: 100%;
        height: 1PX;
        transform-origin: 50% 100%;
        transform: scaleY(0.5);
        @media (min-resolution: 3dppx) {
          transform: scaleY(0.33);
        }
      }
    }
  }
}

.hairline(@direction, @color: @border-color-base) when (@direction = 'left') {
  border-left: 1PX solid @color;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      border-left: none;

      &::before {
        .scale-hairline-common(@color, 0, auto, auto, 0);
        width: 1PX;
        height: 100%;
        transform-origin: 100% 50%;
        transform: scaleX(0.5);

        @media (min-resolution: 3dppx) {
          transform: scaleX(0.33);
        }
      }
    }
  }
}

.hairline(@direction, @color: @border-color-base, @radius: 0) when (@direction = 'all') {
  border: 1PX solid @color;
  border-radius: @radius;

  html:not([data-scale]) & {
    @media (min-resolution: 2dppx) {
      position: relative;
      border: none;

      &::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        width: 200%;
        height: 200%;
        border: 1PX solid @color;
        border-radius: @radius * 2;
        transform-origin: 0 0;
        transform: scale(0.5);
        box-sizing: border-box;
        pointer-events: none;

        // @media (min-resolution: 3dppx) {
        //   width: 300%;
        //   height: 300%;
        //   border-radius: @radius * 3;
        //   transform: scale(0.33);
        // }
      }
    }
  }
}

這個(gè)值得研究下,比 vant 和 第一種解決方案有點(diǎn)不同,主要在于處理了 DPR 為 2 和為 3 的兩種情況,相比來(lái)說(shuō)更加完善。

這里 PX 大寫(xiě),為了防止插件將 px 轉(zhuǎn)成 rem 等單位。

到此,相信大家對(duì)“html中移動(dòng)端1px問(wèn)題實(shí)例分析”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI