網(wǎng)站的首頁(yè)響應(yīng)速度極其重要最欠,這直接決定了新用戶是選擇留下還是選擇放棄你的站點(diǎn)。有統(tǒng)計(jì)數(shù)據(jù)顯示妖啥,用戶的耐心通常<2秒。最好能讓你的頁(yè)面在2秒內(nèi)呈現(xiàn)对碌,起碼部分呈現(xiàn)荆虱,否則時(shí)間越往后,你的站點(diǎn)被用戶放棄的可能性越將指數(shù)級(jí)上升朽们。
提高頁(yè)面響應(yīng)速度的需要考慮很多方面怀读,其中非常重要的一項(xiàng)就是盡量減少HTTP請(qǐng)求的次數(shù)。
通常網(wǎng)站會(huì)對(duì)腳本文件和CSS文件進(jìn)行了合并處理骑脱,這樣用戶在第一次無(wú)任何緩存的前提下菜枷,(統(tǒng)計(jì)數(shù)據(jù)顯示)訪問(wèn)米國(guó)排名前十的門(mén)戶網(wǎng)站平均只會(huì)加載6-7個(gè)腳本文件和1-2個(gè)CSS文件。合并處理大大減少了HTTP請(qǐng)求的次數(shù)叁丧。那么圖片呢啤誊?本篇將探討一下如何技巧性地加載圖片的方式以提高網(wǎng)站響應(yīng)速度。
- 圖片內(nèi)聯(lián)
- CSS Sprites
- Image Map
圖片內(nèi)聯(lián)
常見(jiàn)的加載圖片的方式如:<img src=”img/25/1.jpg” />
會(huì)導(dǎo)致一次HTTP請(qǐng)求拥娄,請(qǐng)求服務(wù)器回傳圖片蚊锹。其實(shí)圖片的本質(zhì)也是數(shù)據(jù),如果能直接獲得圖片的數(shù)據(jù)稚瘾,就可以直接讓屏幕繪制該圖片牡昆,避免了HTTP請(qǐng)求。
獲取圖片數(shù)據(jù)可以用FileReader的readAsDataURL方法孟抗,你也可以參照HTML5 Doctor里關(guān)于生成圖片預(yù)覽的說(shuō)明迁杨,原理都是一樣的。
用JS寫(xiě)個(gè)小工具凄硼,代碼其實(shí)沒(méi)幾行铅协,如果懶得寫(xiě)。也有現(xiàn)成的工具站點(diǎn)如Encode Data URL(有興趣可以查看該頁(yè)面源碼摊沉,同樣是通過(guò)File API實(shí)現(xiàn)的狐史,原理也是一樣的),可以讓你輕松獲取圖片的數(shù)據(jù)。獲取到的數(shù)據(jù)被封裝到了Data URL里骏全,之后將Data URL傳遞給img的src或background-image的URL等屬性即可實(shí)現(xiàn)圖片內(nèi)聯(lián)苍柏。
例如將本地圖片拖動(dòng)到工具站點(diǎn)Encode Data URL里,自動(dòng)生成的Data URL:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg……U+LQ/9k=
//data:image/jpg;為數(shù)據(jù)協(xié)議及類(lèi)型名
//base64為數(shù)據(jù)編碼格式
//后面一串就是經(jīng)Base64編碼后的圖片數(shù)據(jù)了
將上面的Data URL直接塞入CSS端的img的src屬性里即可:<img src=”data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABg…U+LQ/9k=” />
現(xiàn)在瀏覽器可以直接顯示圖片姜贡,不必再通過(guò)HTTP請(qǐng)求和服務(wù)器交互了试吁。而且因?yàn)槭菫g覽器直接顯示,規(guī)避了跨域的問(wèn)題楼咳。
但圖片內(nèi)聯(lián)也不是沒(méi)有缺點(diǎn)的:
- 比如圖片一旦更新就需要同步更新CSS里Data URL的值熄捍,而用普通的圖片加載方式的話,服務(wù)器端直接替換同名圖片即可母怜。
- 比如Base64編碼后數(shù)據(jù)大小會(huì)變大余耽,因此將Data URL寫(xiě)入CSS后,CSS增加的大小會(huì)大于圖片的實(shí)際大小苹熏。雖然CSS可以gzip壓縮碟贾,而圖片不能壓縮,但龐大的CSS文件是不可取的轨域。
- 比如舊版本的IE6/7不支持(說(shuō)真的袱耽,放棄它們吧)。
結(jié)合內(nèi)聯(lián)圖片的優(yōu)缺點(diǎn)疙挺,圖片內(nèi)聯(lián)最好用于很少變更扛邑,且實(shí)際尺寸很小的圖片。
CSS Sprites
CSS Sprites將多張圖片合并成一張铐然。所謂一圖勝千言:
合并成一張圖片后蔬崩,原本多次HTTP請(qǐng)求減少為1次。加載后用background-position位置偏移來(lái)顯示需要的圖片搀暑。例如:
#navbar span {
width: 31px;
height: 31px;
float: left;
background-image:url(/images/navbar.gif);
}
.nav1 {background-position:0 0; margin-right:4px;}
.nav2 {background-position:-32px 0; margin-right:4px;}
.nav3 {background-position:-64px 0; margin-right:4px;}
……
按常理合并圖片后邊緣處會(huì)有一些多余的空白部分沥阳,理應(yīng)合并后尺寸變大才對(duì)。但出乎預(yù)料的是多張圖片合并成一張后自点,合并后的尺寸要比多張圖片加起來(lái)的尺寸要小桐罕。因?yàn)榭梢怨蚕砩恚鴨为?dú)的一張圖片會(huì)有單獨(dú)的色表桂敛。
CSS Sprites的缺點(diǎn)主要是后期維護(hù)困難功炮,一旦圖片要發(fā)生變動(dòng),很容易導(dǎo)致CSS里位置重新計(jì)算偏移量术唬。況且Photoshop切圖合并也不是很容易的事薪伏。
因此CSS Sprites一般用于不常變動(dòng)的背景,按鈕粗仓,導(dǎo)航條嫁怀,鏈接等地方设捐。但如果圖片太多,一張龐大的合并圖可能是后期維護(hù)的惡夢(mèng)塘淑。
Image Map
如上例用CSS Sprites合并成一張導(dǎo)航條圖片后萝招,還可以用Image Map。用<map>標(biāo)簽直接在一張圖片上綁定多個(gè)連接存捺,這樣就不需要background-position位置偏移來(lái)顯示圖片了:
<img usemap="#map1" src="/images/navbar.gif">
<map name="map1">
<area shape="rect" coords="0,0,31,31" href="nav1.html" title="nav1">
<area shape="rect" coords="36,0,66,31" href="nav2.html" title="nav2">
<area shape="rect" coords="71,0,101,31" href="nav3.html" title="nav3">
……
</map>
效果顯然易見(jiàn)槐沼,如果你想在圖片不同區(qū)域點(diǎn)擊獲得不同效果,可以告別請(qǐng)求多張圖片并在頁(yè)面端拼圖的方式了召噩。在本地處理合并好圖片后母赵,用Image Map可以有效減少HTTP請(qǐng)求數(shù)量。
總結(jié)
圖片是網(wǎng)頁(yè)不可或缺的一部分具滴,而且加載圖片通常比較吃帶寬,對(duì)圖片應(yīng)該盡量用緩存和CDN來(lái)加快頁(yè)面顯示速度师倔。但首次訪問(wèn)站點(diǎn)沒(méi)有緩存或緩存過(guò)期時(shí)构韵,上面3種方式(僅我所知)可以減少HTTP請(qǐng)求次數(shù),并部分縮小圖片尺寸趋艘,來(lái)加速頁(yè)面的響應(yīng)的速度疲恢。