移動端使用 rem 單位時 css sprites 定位問題

如今開發移動端 wap 頁面,相信你們都會使用強大的 rem 單位去適配各類機型和屏幕;爲了減小網絡請求數量,提升網頁訪問性能,通常都會把多個小 icon 合併成一張 sprite 圖,而後根據 background-position 進行定位;可是因爲計算機的計算誤差,經常會致使 icon 的顯示有1到2像素的誤差;css

1、PC 端

若是在 PC 端,雪碧圖的定位其實很是簡單,很少說,直接上代碼:html

html 代碼瀏覽器

<ul class="sprites-box">
    <li class="icon icon-bill"></li>
    <li class="icon icon-emailmsg"></li>
    <li class="icon icon-import"></li>
    <li class="icon icon-music"></li>
    <li class="icon icon-pay"></li>
    <li class="icon icon-search"></li>
    <li class="icon icon-speak"></li>
    <li class="icon icon-task"></li>
</ul>
複製代碼

css 代碼bash

body, ul { margin: 0; }
ul { padding: 50px; list-style: none; overflow: hidden; }
li { float: left; margin: 10px; }
.icon { background-image: url('./sprite.png'); }
.icon-bill { background-position: -35px 0px;  width: 32px; height: 32px; }
.icon-emailmsg { background-position: 0px -32px; width: 32px; height: 32px; }
.icon-import { background-position: -32px -32px; width: 32px; height: 32px; }
.icon-music { background-position: -67px 0px; width: 32px; height: 32px; }
.icon-pay { background-position: 0px 0px; width: 35px; height: 32px; }
.icon-search { background-position: -67px -32px; width: 32px; height: 32px; }
.icon-speak { background-position: 0px -64px; width: 32px; height: 32px; }
.icon-task { background-position: -32px -64px; width: 32px; height: 32px; }
複製代碼

效果網絡

sprite

由於其使用 px 定位,且屏幕單位和倍率都是固定的,因此能夠完美的實現雪碧圖效果;併發

2、移動端

在移動端,因爲各類機型的屏幕倍率,使得使用 px 做爲單位的佈局會有很大的適配問題,因此如今主流的適配方案就是使用 rem 做單位,而且根據屏幕倍率計算 rem 的基值進行適配;less

本人是以寬爲 750 的設計稿爲基礎,每 1rem 的值爲設計稿中 100px 的長度; 因爲 icon 的大小尺寸基本一致,故稍微作了點處理,裁切掉了 icon 的透明部分,合成尺寸不統一的 sprite 圖;佈局

一、直接轉換爲 rem 單位

換算後以上雪碧圖的 css 代碼爲:性能

body, ul { margin: 0; }
ul { padding: 0.5rem; list-style: none; overflow: hidden; }
li { float: left; margin: 0.1rem; }
.icon { background-image: url('./sprite.png'); background-size: 0.96rem 0.92rem; background-repeat: no-repeat; }
.icon-bill { background-position: -0.67rem -0.26rem; width: 0.28rem; height: 0.26rem; }
.icon-emailmsg { background-position: 0 -0.64rem; width: 0.26rem; height: 0.28rem; }
.icon-import { background-position: -0.26rem -0.64rem; width: 0.26rem; height: 0.28rem; }
.icon-music { background-position: -0.35rem 0; width: 0.32rem; height: 0.32rem; }
.icon-pay { background-position: 0 0; width: 0.35rem; height: 0.32rem; }
.icon-search { background-position: -0.32rem -0.32rem; width: 0.29rem; height: 0.27rem; }
.icon-speak { background-position: 0 -0.32rem; width: 0.32rem; height: 0.32rem; }
.icon-task { background-position: -0.67rem 0; width: 0.29rem; height: 0.26rem; }

複製代碼

效果:ui

sprite_mobile1

細心留意能夠看出,部分地方顯示會有大概 1px 的誤差,這是因爲不一樣手機計算誤差致使的,若是 icon 較爲簡單,能夠接受這種效果也不要緊,若是對 icon 顯示的要求較高,則這種方式很明顯不能達到要求;

二、轉換爲 rem 後經過 百分比進行定位

首先確認 background-position 使用百分比定位的概念:

屬性值爲百分比時,將以指定的點爲重合點擺放雪碧圖和顯示 icon 的框。 簡而言之,假設值爲 10% 20%,則是將 sprite 圖的 10% 20% 位置的點與顯示框 10% 20% 的點重合(並非 0% 0% 的點)

舉個栗子: 有一張 200X200 的 sprite 圖,和一個 50X50 的 icon 顯示框,這時若是設置 background-position: 0% 0%;

效果以下:

position0%0%

若是設置 background-position: 100% 100%; ,會先獲取 icon 框 100% 100% 位置的點,和 sprite 圖 100% 100% 位置的點,而後將其重合;

效果以下:

position100%100%ready
position100%100%result

由此可知: 其百分比定位的效果至關於先將 icon 框左上角的位置定位到 sprite 圖 100% 100% 的位置,再往左上方回挪 icon 框 100% 100% 的位置;

這是在咱們知道百分比的狀況下實現的效果,而拿到 sprite 圖的時候,咱們每每知道的信息以下:

  • 每一個 icon 的大小
  • sprite 圖的大小
  • 每一個 icon 在 sprite 圖中的定位

這時候咱們就須要經過已知的條件計算出定位的百分比,這就變成了一道數學題:

已知 icon 寬高都爲 50,sprite 寬高都爲 200,icon 左上角在 sprite 內的座標爲 (50, 60),計算其 background-position

解:
由於 background-position 定位的概念爲 icon 框和 sprite 圖各自指定位置重合;
設:sprite 寬爲 W,高爲 H,icon 寬爲 w,高爲 h,icon 在 sprite 中的座標爲 (x,y),獲得百分座標爲 (m,n) 故可獲得如下公式:
mW-mw=x  =>  m(W-w)=x  =>  m=x/(W-w)*100%
nH-nh=y  =>  n(H-h)=y  =>  n=y/(H-h)*100%
計算可得:
m=50/(200-50)*100%=33.3%
n=60/(200-50)*100%=40%
複製代碼

固然,公式是上面那樣,若是寫到 css 中,就須要配合 css 的計算方法 calc() 進行計算,若是對 calc 不明確的同窗自行百度一下;若是同窗使用 scss 或者 less 等 css 預編譯器編寫樣式的就更簡單了,直接寫一個混入方法就搞定;

三、其餘方式

  • 每一個小圖標使用單張圖片,再經過 background-size: cover|100%|contain; 也能完美的顯示,可是一個頁面的圖標多的時候,請求就太多了,瀏覽器的併發請求數是有限制的,這樣會致使網頁的加載時間大大加長,不划算;
  • 每一個小圖標轉成 base64 圖片,再直接寫入代碼:
    • 優勢:1. 完整顯示圖標;2. 減小請求數量;
    • 缺點:1. 色彩豐富的圖片轉成 base64 效果很差;2. 會增大圖片說起,至關於用下載時間換取請求時間;

好了,這篇分享就說到這裏,初次寫文章,語句和方式不免有瑕疵,望各位看客老爺見諒。

相關文章
相關標籤/搜索