淺談 CSS Sprites 雪碧圖應用

網站開發90%會用到小圖標, 多小圖標調用顯示是前端開發常見的問題;目前小圖標顯示常見有兩種方式(其他方式歡迎補充):

1.圖標字體 顯示;如小米官網左側菜單欄:

2.CSS Sprite(CSS 精靈), 也稱作 雪碧圖;如華為官網右側提示欄:

圖標字體是個比較大的技術討論點, 關於它可以出好幾篇博文,可惜本文主角不是它, 今天主要探討下 CSS Sprite -- 雪碧圖 的各種實現。

CSS 雪碧圖簡介

開始說雪碧圖各種實現前, 簡單說下什麼是雪碧圖?雪碧圖的原理是什麼?

什麼是雪碧圖?

雪碧圖也叫CSS精靈, 是一CSS圖像合成技術;

上面解釋說它是一項技術,但我們開發人員往往將小圖標 合併在一起之後的圖片稱作雪碧圖;術語定義其實不用糾結, 我們知道它主要用在小圖標顯示上就行了。

CSS 雪碧圖應用原理:

只有一張大的合併圖, 每個小圖標節點如何顯示單獨的小圖標呢?

其實就是 截取 大圖一部分顯示,而這部分就是一個小圖標,如下圖:

如顯示上面 QQ 小圖標, 則在合併圖中X軸向右60像素, Y軸0像素, 截取寬高均為48像素;則 這個小圖標就出來了:

關鍵樣式:

background-image: url("sprite.png");nbackground-position: -60px 0px;nwidth:48px;nheight:48px;n

接下來, 就開始進入實踐環節, 如果我們要實現如下效果, 該怎麼做呢?

按正常開發流程, 我們的設計部同事會給我們這樣的一個設計稿(實際設計稿會有更多無關圖層):

然後就是前端作為切圖仔表現的時候了, 簡單說下切圖步驟(高級切圖仔請跳過):

1.裁剪工具(快捷鍵C), 選中 切片工具:

2.選中要導出的圖標(建議快鍵鍵z用縮放工具放大然後選切圖區):

3.導出為web格式圖片快捷鍵:Alt+Shift+Ctrl+S(mac: Alt+Shift+Commond+S)

需要說下的, 新版本 photoshop 從2015 CC開始就不用這麼麻煩去切圖了, 直接選中小圖標圖層右鍵「快速導出為PNG」, 即可得到對應小圖標的png文件;

Photoshop軟體版本不夠新怎麼辦? 你可以看看 21款強大高效的Photoshop擴展插件

第10個Breezy 即為切圖插件;快速導出 或 切圖 成功後, 就有了以下四個小圖標了:

小圖標素材整理好後, 接下里就是針對上述頁面效果的各種實現以及對比了。

傳統網頁調用小圖標(原始方式)

首先說下雪碧圖技術沒推廣開來 或 新手小白開發以上效果時, 是這樣實現的:

demo地址:

小圖標調用Demo(原始版)

代碼地址:

小圖標調用源碼(原始版)

分別為四個小圖標定義不同的四張小圖標, 關鍵樣式代碼:

.ps_demo_wrap .demo_icon{ntposition: relative;ntfloat:left;ntmargin:13px 0px 0px 10px;ntcursor: pointer;ntwidth:54px;ntheight:54px;n}n.ps_demo_wrap .weibo_icon{ background-image:url("../scss/images/icon_weibo.png"); }n.ps_demo_wrap .qq_icon{ background-image:url("../scss/images/icon_qq.png"); }n.ps_demo_wrap .douban_icon{ background-image:url("../scss/images/icon_douban.png"); }n.ps_demo_wrap .renren_icon{ background-image:url("../scss/images/icon_renren.png"); }n

不使用雪碧圖, 單純調用小圖片有以下優缺點:

優點:調用簡單、維護方便;n

缺點:請求文件過多、引發性能問題;

為什麼不建議使用該方式顯示小圖標?

每個小圖標都單獨調用一圖片, 即意味著每個小圖標的顯示都產生一個HTTP請求;學習過HTTP相關知識應該知道,一般情況下每次創建一 HTTP請求,請求到的內容 往往是次要的(除非文件特別大), 性能開銷主要在請求、以及響應階段;使用以上方式實現如 鬥魚直播間雪碧圖或以下知乎的雪碧圖, 造成的性能消耗肯定不小!

綜上所述, 網站開發中遇到小圖標顯示, 優先考慮雪碧圖實現; 那麼問題來了, 小圖標合併成一張圖片,如果需求有改動導致雪碧圖修改(新增或修改小圖標), 更糟糕的是多個開發人員的功能模塊都得調用該雪碧圖(意味著多人會修改到雪碧圖), 該如何開發、維護雪碧圖呢?

雪碧圖實現1: CSS Gaga

慕課網雪碧圖教程推薦軟體,CssGaga 幫助索引

PS: 該軟體只有windows版本, 並未找到mac版;

CssGaga如何實現雪碧圖呢?

1.下載安裝該軟體;

2.選中「圖片合成」菜單後, 將小圖標拖入軟體首頁即可生成對應的雪碧圖以及CSS Sprite代碼;

3.根據上述生成的雪碧圖以及對應圖標位置,編寫CSS;

.ps_demo_wrap .weibo_icon,n.ps_demo_wrap .qq_icon,n.ps_demo_wrap .douban_icon,n.ps_demo_wrap .renren_icon{n width:54px;n height:54px;n background:url("../images/CssGaga.png");n}n.ps_demo_wrap .weibo_icon{ background-position: -168px 0px; }n.ps_demo_wrap .qq_icon{ background-position: -56px 0px; }n.ps_demo_wrap .douban_icon{ background-position: 0px 0px; }n.ps_demo_wrap .renren_icon{ background-position: -112px 0px; }n

demo地址:

雪碧圖實現1Demo

代碼地址:

雪碧圖實現1源碼

實現方案1問題比較多:

1.只支持windows操作系統, 對於很多mac開發的人而言不友好;

2.多人維護雪碧圖時,溝通成本較高(得確認新的雪碧圖中舊小圖標位置是否有變化);

接下來分析的實現方案2普及率比較高, 應該是目前大部分前端組的實現方式;

雪碧圖實現2:photoShop

雖然我們不是設計人員,但作為傳統web開發人員photoShop幾乎是必學技能; 當然隨著前端技術的不斷發展, 前端開發人員使用photoShop的幾率會越來越少;

回歸正題, 雪碧圖的實現方案2就是使用photoShop來生成雪碧圖, 並且雪碧圖以PSD文件格式保留, 後續修改圖標(或新增圖標)只需要找到並修改該PSD即可, 再也不用保存原來的小圖標了~

實現步驟:

1.下載(mac 版、windows版)PS軟體;

2.新建PSD文件根據設計稿確定初始大小:300*150;

3.複製設計稿圖層;

4.雪碧圖PSD新建參考線;

5.根據參考線確定小圖標位置;

6.使用裁剪工具裁剪後,PSD導出為png, 快捷鍵: Alt+Shift+Ctrl+S(mac: Alt+Shift+Commond+S);

7.獲取小圖標大小、位置;

選中圖層, Ctrl+T (mac: Commond + T), 在信息面板查看圖層信息;

8.根據雪碧圖 編寫對應CSS;

以上步驟雖然多 熟悉後其實很快, 但 其對新手而言的確不友好;

demo地址:

雪碧圖實現2Demo

代碼地址:

雪碧圖實現2源碼

實現方案2問題:

1.操作PSD步驟有點多, 需要開發人員熟悉PS操作;

2.PSD文件比較大, 也不太適合保存在項目中, 一般放SVN共享維護;(SVN伺服器宕機、PSD文件衝突等也需要不少時間成本)

好了,接下來分析的是實現方式3, 使用自動化部署工具gulp生成雪碧圖,也是本文推薦的雪碧圖實現方式!

雪碧圖實現3:gulpn

如果讀者從未聽說gulp或者對gulp了解的比較少, 建議網上搜索並閱讀gulp相關資料後繼續觀看以下內容!

gulp環境搭建無非就是 安裝nodejs 然後通過npm(建議使用cnpm)安裝gulp模塊;

具體可參考:前端構建工具gulp的使用;

使用gulp自動生成雪碧圖有兩種實現方式

gulp生成 css 代碼

實現步驟:

1.安裝 gulp 開發雪碧圖的依賴模塊,具體要哪些模塊可參考本demo的配置文件;

PS: 為什麼不直接參考本demo的package.json文件?因為本demo所在工程引用的其他nodejs模塊較多容易造成干擾。

2.編寫配置文件, 以下是關鍵配置代碼:

/*n* 雪碧圖合併task( 輸出到 css文件 )n* 參數1:執行目錄;n* 參數2:生成的sass和圖片的文件名;n* example:gulp sprite-css --scss --index_css_gulpn*/ngulp.task(sprite-css, function(){n var DEST_NAME = args[1];n return gulp.src(`${WATCH_SRC}/**/*.png`)n .pipe(spritesmith({n imgName: DEST_NAME + .png,n cssName: DEST_NAME + .css,n imgPath: ../images/ + DEST_NAME + .pngn }))n .pipe(gulpif(*.png, gulp.dest(images/)))n .pipe(gulpif(*.css, gulp.dest(css/)));n});n

之所以推薦gulp, 是因為gulp非常的靈活, 看懂gulp模塊的API可以根據你的項目情況編寫對應的配置文件。所以以上配置文件只是一個參考, 實現的功能幾乎不可能遷移到其他項目。

3.編寫好配置文件後, cmd(windows)或終端(mac)到配置文件同級目錄(gulpfile.js, gulp規定配置文件名字必須為gulpfile)然後執行指令:

gulp sprite-css --scss --index_css_gulpn

就會在指定路徑生成index_css_gulp.css 以及 index_css_gulp.png, 一般是拷貝index_css_gulp.css樣式後再刪除該css文件, 本demo功能比較簡單, 所以直接在index_css_gulp.css添加新樣式;

demo地址:

雪碧圖實現3_1Demo

代碼地址:

雪碧圖實現3_1源碼

gulp 生成 sass 代碼(推薦)

比起上述用gulp生成css代碼, 本人更推薦使用gulp生成sass代碼,因為你已經安裝了gulp了那順便安裝下gulp-sass很簡單。越是大型的項目, sass 的優勢越明顯, 當然小項目用它也不差。(sass可以明顯提高編寫樣式的效率)

實現步驟:

1、2、3步驟同上, 只是第三步驟指定的指令為:

gulp sprite --scss --mySpriten

關鍵配置代碼:

/*n* 雪碧圖合併task( 輸出到 scss文件)n* 參數1:執行目錄;n* 參數2:生成的sass和圖片的文件名;n* 參數3:輸出目錄(非必填),不填的話輸出目錄為執行目錄n* example:gulp sprite --scss --mySpriten*/ngulp.task(sprite, function(){n var DEST_SRC = args[2] !== undefined ? args[2] : args[0];n var DEST_NAME = args[1];n var spriteData = gulp.src(`${WATCH_SRC}/**/*.png`).pipe(spritesmith({n imgName: DEST_NAME + .png,n imgPath: ../images/ + DEST_NAME + .png,n cssName: _ + DEST_NAME + .scssn }));nn var imgStream = spriteData.imgn .pipe(buffer())n .pipe($.imagemin())n .pipe(gulp.dest(images));nn var cssStream = spriteData.cssn .pipe(gulp.dest(`${DEST_SRC}`));nn return merge(imgStream, cssStream);n});n

執行完指令後會在對應目錄生成_mySprite.scss 、mySprite.png, 根據sass語法帶「_」前綴的文件為調用模塊, 只能被其他sass文件調用不會被編譯成同名css文件;生成的_mySprite.scss文件手動添加到目標樣式index.scss中調用, 然後通過監聽(配置文件的sass:watch)自動生成index.css文件,配置文件可以在執行指令的時候指定路徑,所以能適應更多的場景。

demo地址:

雪碧圖實現3_2Demo

代碼地址:

雪碧圖實現3_2源碼

實現方案3問題:

1.gulp 相關知識得熟悉才能寫出對應的配置文件;

2.如使用gulp生成scss文件還得學習sass相關資料;

PS: gulp 跟 sass 都是大部分前端組要求掌握的技能;

雪碧圖實現4:webpack

說到webpack很多人會聯想到ReactJs, 的確前段時間 ReactJs 的大熱讓更多的人知道了webpack, 但webpack並不是ReactJs內置的模塊, 它是德國人開發出來的模塊載入工具。因為很好用所以被ReactJs作為推薦載入工具, webpack可以跟其他庫一起完成項目,本demo單獨使用webpack完成。

實現步驟:

1.配置webpack開發環境(其實也是安裝nodejs環境+cnpm安裝對應模塊而已);

2.安裝雪碧圖依賴模塊:webpack-spritesmith;

3.將素材小圖標放入對應文件夾,編寫配置文件-webpack.config.js:

var path = require(path);nvar SpritesmithPlugin = require(webpack-spritesmith);nnmodule.exports = {n entry: path.resolve(__dirname, app/main.js),n output: {n path: path.resolve(__dirname, build),n filename: bundle.js,n },n plugins: [n new SpritesmithPlugin({n src: {n cwd: path.resolve(__dirname, app/images/),n glob: *.pngn },n target: {n image: path.resolve(__dirname, build/images/sprite.png),n css: path.resolve(__dirname, build/css/sprite.css)n },n apiOptions: {n cssImageRef: ../images/sprite.pngn },n spritesmithOptions: {n algorithm: top-downn }n })n ]n};n

4.在配置文件同級目錄下,執行指令:

webpackn

同實現3_1在生成的sprite.css手動添加樣式demo就完成了!該實現方式類似gulp, 都使用「 spritesmith」模塊,都寫配置文件+執行指令生成雪碧圖,當然webpack方式也可以生成scss文件, 限於本文篇幅就不做介紹了(其實是還不會[一臉懵逼撓頭])。

demo地址:

雪碧圖實現4Demo

代碼地址:

雪碧圖實現4源碼

實現方案4問題:

1.需要學習webpack相關知識;(現在webpack官網教程完善些了,不像早些時候官網教程外鏈到別人博客,評論區里各種吐槽表情包~~~)

2.webpack是一套完整的模塊引用工具,不止樣式, 其他功能不一定用的上。

結語:

除了 gulp 跟 webpack 外,還有國產前端部署的解決方案FIS3, 其對小圖標也有一套部署配置流程, 因為不了解就不寫了, 感興趣的同學可以去學習下;webpack跟FIS3包含的其他功能多一些(特別是FIS3可稱為完整的解決方案),一般項目如果大方向的技術選型沒定webpack或FIS3,就單純完成雪碧圖而言不太推薦;

最後說明下, 上述的demo實現是有瀏覽器兼容問題的, IE8(包括IE8)以下版本不支持圓角和rgba單位值:

border-radius:50%;nbackground-color: rgba(0,0,0,.5);n

rgba顏色方面倒是可以使用透明+濾鏡(低版本瀏覽器)實現, 圓角就只有新增圖標了, 當然以上只是demo不用在意其他細節了哈~

參考資料:

CSS Sprite實踐應用-慕課網

Photoshop實踐分享PPT

HTTP協議詳解

21款強大高效的Photoshop擴展插件

CssGaga 幫助索引

前端構建工具gulp的使用

十分鐘學會sass

webpack中文指南


推薦閱讀:

一道滴滴的負載均衡前端面試題
2018 前端性能優化清單 —— 第一部分
前端瀏覽器緩存及代碼部署
有哪些比較好 CSS 簡寫(壓縮)工具?

TAG:CSS | 前端性能优化 | 图标 |