1. 程式人生 > >rem佈局下使用背景圖片和sprite圖

rem佈局下使用背景圖片和sprite圖

現在移動端頁面用rem佈局已經是一大流派了,成熟的框架如淘寶的flexiable.js,以及更輕量級的hotcss。用rem作單位使得元素能夠自適應後,還有一塊需要關注的,那就是背景圖片。本文就來聊聊這方面的東西。

rem佈局

所謂rem佈局就是指為文件的根節點<html>元素設定一個基準字型大小,然後所有的元素尺寸都以rem為單位來寫。比如將<html>的字型設為100px,如果需要做一個100*200的元素,css如是寫:

div{
    width: 1rem;
    height: 2rem;
}

那麼最終得到的元素寬高就是100*200px了。

為了能夠在不同尺寸的手機螢幕上自適應,需要用js來判斷手機寬度,並動態設定<html>的字型大小,這樣基準字型變了,元素的尺寸自然相應變化,達到了自適應的效果。

此處只介紹基本概念,rem佈局方案的其他細節不是本篇的範疇。最早提這個方案的應該是winter寒老溼,有沒有人更早使用我就不好考證了。

雙倍設計稿

為了能在視網膜屏下清晰顯示,現在的設計稿一般都是基於iPhone5的寬度(320)或者iphone6的寬度(375),進行雙倍。也就是說,設計稿的寬度一般是640或者750.

這個尺寸也不是絕對的,因為iPhone6 plus的dpr值為3,也有設計稿進行三倍尺寸,這樣能在iPhone6 plus上完美顯示。當然對於Android裝置來說情況就更復雜了,dpr值什麼樣的都有,所以雙倍設計稿算是一個折中方案,大體上能保證所有裝置清晰顯示圖片。

此時,我們在頁面上還要做一件事情,那就是動態設定<meta>中的viewport屬性,將scale改成0.5(dpr為2)或者其他值,這樣我們寫css的時候,就可以按照原設計稿的尺寸來寫了。

我們切出來的圖片是雙倍大小,但是頁面上的元素已經被動態縮小了,如果要做背景圖片的話,得想辦法讓圖片跟著縮小才行。

cover與contain

CSS3為background-size屬性增加了兩個值:cover與contain。這個兩個值允許我們指定背景圖片的自適應方式。它倆有什麼區別呢?

從語言上描述,cover是拉伸圖片使之充滿元素,元素肯定是被鋪滿的,但是圖片有可能顯示不全。contain則是拉伸圖片使圖片完全顯示在元素內,圖片肯定能顯示全,但是元素可能不會被鋪滿。

上面說的“可能”的情況,發生在元素尺寸和圖片尺寸寬高比例不一致的時候。

下面通過例子來演示一下這兩者的用法。比如我們以iPhone5為例,此時dpr為2,頁面scale為0.5,基準字型大小為100px。設計稿上有一張90*200px的圖片。那麼css應該這麼寫:

複製程式碼 複製程式碼
#mm{
    width: 0.9rem;
    height: 2rem;
    background-image: url(mm.jpg);
    background-size: contain;
    background-repeat: no-repeat;
}
複製程式碼 複製程式碼

效果如下:

當元素與背景圖片的大小一樣,或者是寬高比例一致時,contain和cover的填充效果是一樣的,因為兩者在拉伸後總能使圖片“恰好”完全充滿元素。

但是有時候元素的寬高比例是不確定的,比如有一張寬度為100%,高度為200px的圖片。此時contain和cover的區別就顯示出來了。如下圖:

可以看到contain的時候,元素右側有空白沒有填滿。而cover的時候,元素雖然填滿了,但是有一部分圖片已經拉伸到元素外部看不到了。這就是兩者的區別,實際應用的時候要根據具體情況來定。

background-size取具體值

大家知道background-size可以取具體的值以及百分比,那麼我們直接把背景圖片大小設定為跟元素大小一樣不就完了嗎?還費什麼勁搞什麼自適應。

當然是可以的。比如我們把上面的css改成這樣:

複製程式碼 複製程式碼
#mm{
    width: 0.9rem;
    height: 2rem;
    background-image: url(mm.jpg);
    background-size: 0.9rem 2rem;
    background-repeat: no-repeat;
}
複製程式碼 複製程式碼

完全可以實現同樣的效果。

只是我本人在寫css的時候很不喜歡寫具體值,一般是能自適應就自適應。這樣如果後期要改動元素的大小,只要改一處就行,所以我更喜歡用contain或cover。

sprite圖片的處理

為了合併圖片請求我們經常會用到sprite技術。在rem佈局方案下,使用contain或cover來縮放背景圖片就無法奏效了。因為元素的背景其實是sprite圖片的區域性,contain和cover只能對整張圖片進行縮放,沒辦法控制到區域性的大小。

比如有如下一張200*50的sprite圖。

 image

在使用contain縮放後是這樣的

所以在處理sprite圖片時,我們只能給background-size取具體值。那麼這個值取多少呢?其實只要寫我們切出來的圖片的實際尺寸就行。

比如我們的元素為50*50px,sprite圖片為200*50px,那css應該如下:

複製程式碼 複製程式碼
#cpt{
    width: 0.5rem;
    height: 0.5rem;
    background-image: url(cpt.png);
    background-size: 2rem 0.5rem;
}
複製程式碼 複製程式碼

然後修改background-position我們就可以取到sprite上的其他圖片了。background-position也取具體值,也是按照切出來的圖的尺寸就行。

比如我這張圖片是一個幀動畫的4個幀,每一幀的背景圖片應該如下:

複製程式碼 複製程式碼
#cpt.status1{
    background-position: 0 0;
}
#cpt.status2{
    background-position: -0.5rem 0;
}
#cpt.status3{
    background-position: -1rem 0;
}
#cpt.status4{
    background-position: -1.5rem 0;
}
複製程式碼 複製程式碼

利用這個尺寸,我們來做個小動畫試試。