HTML和CSS高級指南之一——性能與架構

本文由99根據Shay Howe的《An Adavnced Guide to HTML & CSS》第一課《Performance & Organization》所譯,整個譯文帶有咱們本身的理解與思想,若是譯得很差或不對之處還請同行朋友指點。如需轉載此譯文,需註明英文出處:http://learn.shayhowe.com/advanced-html-css/performance-organization,以及做者相關信息 javascript

做者:Shay Howe php

譯者:99 css

會書寫html和css,且對他們有深入的理解,是很是可貴的。隨着網站代碼和流量的增加,迫切須要掌握一套新的技能,這對開發時間和用戶體驗來講都是極其重要的。 瞭解網站性能與架構的基本原理,對以後的發展很是有幫助。 html

對代碼進行組織與架構,不只能夠提升開發速度,還會提高頁面的加載速度。這兩個因素對於開發者和用戶來言都是極大關注的。投入時間去設計網站適合的代碼架構,同時確保不一樣組件之間如何共同做用,會加速開發進程,帶來更好的用戶體驗。 前端

此外,只須要幾個小步驟提高網站的性能,你就會獲得回報。網站性能也遵循80/20原則,只須要作20%的優化就能夠提高網站80%的速度。 html5

本課主要內容:

HTML java

CSS git

技巧與結構

提升網站性能和組織的最基本一點,就是探索出一套開發代碼基礎的良好戰略和結構。具體來說,就是創建完備的目錄結構,勾勒設計模式,以及對公用代碼的有效重用。 github

樣式風格 web

如何正確的組織樣式表呢?這與具體網站跟我的偏好都有關係。不過,通常而言咱們也能夠遵循一些最佳實踐。其中一個就是有目的的切分你的樣式表,併爲這些樣式表創建目錄,包括基礎樣式、界面相關的組件,以及商業需求模塊。

# Base – normalize.css
  – layout.css
  – typography.css # Components – alerts.css
  – buttons.css
  – forms.css
  – list.css
  – nav.css
  – tables.css # Modules – aside.css
  – footer.css
  – header.css

以上的代碼組織結構包含三個目錄,都對樣式表作了獨立的分類。這裏要把站點認爲是一個「系統」,而不是不少單獨的頁面,同時,代碼要體現這個思路。要留意以上的組織結構沒有針對「某頁面」的樣式表存在。

Base目錄用來存放公用樣式,以及全站通用的樣式如佈局字體等。Components目錄用來存放特定用戶界面相關的樣式,這些樣式按照界面組件被拆分爲多個文件,好比警告及按鈕。Modules目錄用來存放頁面的不一樣部分,這些部分是由商業需求決定的。

組件樣式是與網站核心的商業邏輯無關的,純粹由界面驅動的樣式。模塊則根據特定的商業邏輯呈現不一樣的樣式。當咱們創建一個模塊時,裏面使用的用戶界面組件一般是不一樣的。舉例來講,一個頁面的側邊欄可能會包含列表及按鈕,這些樣式是定義在組件樣式中的。而其餘的樣式須要從側邊欄樣式中繼承而來,這些樣式是從模塊樣式中定義的。這種樣式分離的原則鼓勵咱們對樣式預先進行仔細的規劃,以及樣式表的共享與重用性。

組織樣式表的策略不是什麼新鮮事物。在以前不一樣的css理論如面向對象的css OOCSS, 可拓展模塊化的CSS, SMACSS 中均提到過這方面的要求。 這些方法論包含他們自身獨特的代碼組織方式,以及樣式表的使用。

面向對象的CSS

面向對象的css是Nicole Sullivan所倡導的,她撰寫大型網站樣式表的一種方法。面向對象的css認爲,兩種原則能夠幫助構建可擴展的,擁有強勁架構及合理的代碼量的網站。

  • 表現與結構分離
  • 內容與容器分離

從一個網站的主題中徹底把皮膚包括元素的佈局結構總體分離。一個模塊的結構是透明的,他能夠繼承任何樣式和不會形成樣式衝突。最多見的就是使用一個網格系統和佈局結構,再結過加工設計成爲一個經典模塊。

內容從容器中分離出來,包括父元素與子元素的嵌套。一個標題應該是同樣的,不管它的父元素是誰。爲了作到這一點,元素須要一些默認的樣式,而後經過多個類名來擴展其樣式是有必要的。

HTML

<div class="alert alert-error"> <p class="msg">...</p> </div>

CSS

.alert {...}
.alert-error {...}
.msg {...}

OOCSS提倡創建組件庫,保持樣式表的靈活性,以及利用網格來佈局。這是很是有效的基本法則,當你要向站點添加頁面或者新需求時,遵循這些原則能夠避免添加額外的樣式表。

可擴展和模塊化CSS

與OOCSS不謀而合的理論是Jonathan Snook提出的:構建可擴展的,模塊化的css架構。如何構建可擴展的,模塊化的css呢?這個理論要求css要拆分爲五個核心類別,包含:

  • 基礎
  • 佈局
  • 模塊
  • 聲明
  • 主題

基礎部分包含一些核心元素的樣式及全局樣式。佈局部分規定了不一樣元素的尺寸與網格樣式,定義了他們的排列規則。模塊部分更加針對頁面某個獨立的部分的特定樣式,好比導航條等。狀態部分定義了一些在某種狀況下用來覆蓋現有模塊表現的樣式,好比一個選定狀態下的tab主題部分可能添加一些樣式好比皮膚,視覺與體驗,不一樣的模塊等。

HTML

<div class="alert is-error"> <p>...</p> </div>

CSS

.alert {...}
.alert.is-error {...}
.alert p {...}
.alert.is-error p {...}

以上的例子裏,alert 這個class的樣式被劃分到模塊類別中,同時 is-error這個class的樣式被劃分到狀態 類別中。以後就能夠按照需求來繼承某個類別中的樣式了。

選擇一種方法

選擇什麼樣的方法去組織代碼,徹底決定於你。你認爲這個方法是對某個網站最適合的,那麼他就是管用的。通常而言適當的混合使用兩種方法是有效的,對於每種方法你能夠按照本身的意願取其精華。

高性能選擇器

Css一個常常被濫用而沒有意識到的功能是選擇器。對於css,人們把注意力都集中在屬性與值上了。他們認爲,只要這些樣式做用到該做用的元素上,元素表現正常就好了。 這是一個很是狹隘的認識。元素在Css中是怎樣被選擇的,與性能息息相關。頁面渲染多快,樣式表結構對於全站來講是否實用,是否模塊化都與css選擇器有關係。

保證簡短的選擇器

保證選擇器儘量簡短是有一些好處的。這些好處包括下降選擇器的權重,提供更好的繼承與可移植性,以及提升效率。冗長且限制過多的選擇器會下降性能,由於這會強迫瀏覽器從右到左的去解析每一個獨立的選擇器。把選擇器更具體化。

<!-- Bad --> header nav ul li a {...} <!-- Good --> .primary-link {...} <!-- Bad --> button strong span {...}
button strong span .callout {...} <!-- Good --> button span {...}
button .callout {...}

上面的代碼中,第一個選擇器過度冗餘,若使用class,會讓元素的識別跟解析變得更快。另外在這個場景裏使用class就不須要判斷元素的父元素了,這樣能夠任意移動元素的位置,而不須要改動任何樣式。

相比第一個例子而言,第二個例子包含一個更短的選擇器,他爲同級選擇器提供了特殊樣式。避免使用權重太高的選擇器,由於當元素次序變化的時候,這類選擇器會解析出不一樣的結果。切分一些獨立的選擇器單元,而後給予他們相同的權重,可讓選擇器之間更好配合。

咱們使用簡短的選擇器的緣由是下降選擇器的權重,書寫一份乾淨且可維護性強的代碼。

傾向於使用class

Class類名是很讚的,渲染速度快,重用性高,已經被普遍應用於網站建設中。不過咱們在使用class的時候,一樣要權衡一些問題。

因爲選擇器是從右到左解析的,因此必定要注意 關鍵字選擇器。 關鍵字選擇器位於選擇器單元的尾端,在最右邊。這個選擇器是很是重要的,由於他標識了瀏覽器要首先查找的元素。一個效率低下的選擇器會給瀏覽器帶來不少無謂的查找工做。不用擔憂使用一個特殊的類名會影響性能。

另一點,在給元素定義樣式時,不要用另外的選擇器來修飾class選擇器。當你用額外的選擇器來限制class選擇器時,你就失去了應用此選擇器到其餘元素的機會,同時增長了整個選擇器的權重。

<!-- Bad --> #container header nav {...} <!-- Good --> .primary-nav {...} <!-- Bad --> article.feat-post {...} <!-- Good --> .feat-post {...}

一樣要留意的是,遠離id選擇器,他們的權重過高,不存在任何可重用性。對於咱們來講使用id與使用!Important沒有什麼明顯區別。

可重用代碼

不斷膨脹的無用代碼是形成性能缺陷最大的緣由之一。而一個有效下降css文件尺寸的方法是儘量的重用樣式。任何重複定義的樣式或者接口模式都須要合併,從而使代碼可被他人使用。若是兩個模塊擁有一樣的背景,圓角,以及盒子陰影,毫無疑問你不能寫兩遍一樣的樣式。所以這些樣式能夠被合併在一個class中來定義。這樣樣式在書寫一次後就能夠再次使用。

重用代碼不會形成語義問題。咱們能夠經過組合多個選擇器的方式,用逗號分割選擇器,讓一樣的樣式經過兩個選擇器來定義並繼承。另一種方法就是遵循上述oocss及smacss所提到的方法,把樣式綁定在一個class類名上,以後能夠用多個class定義本來那個元素。

<!-- Bad --> .news { background: #eee; border-radius: 5px; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25); } .social { background: #eee; border-radius: 5px; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25); } <!-- Good --> .news, .social { background: #eee; border-radius: 5px; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25); } <!-- Even Better --> .modal { background: #eee; border-radius: 5px; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25); }

採起哪一種方法區別不大,當你的代碼被重用後,整個文件的尺寸就會降低。

減少和壓縮文件

下降文件大小最好的方式是去掉重複與無用的代碼。不過對此還有其餘方式可用。其中就包括壓縮html,css與javascript文件。此外,經過去掉無用的信息與顏色配置,圖片也能夠被壓縮。

開啓gzip壓縮

Gzip是最流行的文件壓縮方式之一。Gzip壓縮對一般如html,css javascript等類型的文件進行分析,以後對其字符串進行分析,從而壓縮。Gzip處理過的字符串越多,壓縮後的文件尺寸越小,所以服務器端能夠傳輸更小的文件到瀏覽器端。

設置gzip幾乎不須要任何代價,HTML5 Boilerplate已經對此作了很是好的處理。若是你要對文件進行gzip處理, .htaccess文件須要放到網站服務器根目錄下面,同時將你須要gzip壓縮的特定文件列出來。注意這個文件前面的點號(這是個隱藏文件)。

HTML5 Boilerplate給.htaccess文件單獨開闢了一個部分用來處理gzip壓縮。對於你本身的服務器來講,你能夠重用或者使用一部分文件內的設置,來幫助你開啓gzip壓縮。不過值得注意的是.htaccess文件只能工做在apache web服務器上,並且要開啓下列模塊。

  • mod_setenvif.c
  • mod_headers.c
  • mod_deflate.c
  • mod_filter.c
  • mod_expires.c
  • mod_rewrite.c

一般來說這不是什麼問題,並且有些web服務器爲你已經開啓了壓縮,畢竟壓縮文件也是web服務器最關注的幾個方面之一。

衡量壓縮效果

Chrome瀏覽器開發者工具提供了很是多的數據來度量性能,尤爲是network面板。此外也有一些第三方網站能夠幫你確保gzip壓縮是否開啓。

衡量壓縮效果

Network面板檢視了每一個被瀏覽器加載的文件,且展現了文件大小及加載時間。注意gzip壓縮把文件大小下降了大約60%。

衡量壓縮效果

點擊某個文件,觀察這個文件的請求與響應消息。在這裏能夠確認瀏覽器支持怎樣的方式來壓縮編碼。注意請求頭中的accept-encoding 表示在請求頭中,瀏覽器支持了gzip, deflate 與 sdch注意響應頭中的content-encoding 表示文件是使用gzip壓縮編碼來傳輸的。

 

http協議及請求響應頭的詳細介紹能夠參考深刻理解HTTP協議、HTTP協議原理分析(轉)一文

譯者:99

壓縮圖片

下降文本文件的大小是有效的,若是你對圖像進行壓縮將會取得更好的效果。網站全部圖片的大小輕易就會猛漲,所以對文件進行壓縮將會極大程度的幫助你控制文件尺寸。

不少人對壓縮圖片敬而遠之,緣由是他們擔憂壓縮圖片會下降圖片質量。在大多數狀況下這是不正確的。圖片能夠以無損的方式壓縮,在壓縮時去除無用的顏色配置及圖片信息,一點都不會影響圖片自身質量。

有一些工具來幫助壓縮圖片,在Mac下的ImageOptim和Window下的PNGGauntlet。這兩種是最經常使用來壓縮圖像,特別是JPG和PNG文件。

圖片壓縮的示例

未壓縮前:455kb

圖片壓縮

壓縮後,401kb

圖片壓縮

圖片壓縮

使用ImageOptim 上面的圖片尺寸減少了14%,但圖片質量沒有降低。

一樣要注意的是,在html中設置圖片的寬高也會幫助頁面更快的渲染,設置合適的寬高來爲圖片留出空間。須要明白的是,這些屬性只是爲了確保圖片以準確大小渲染,而不會讓圖片收縮。若是你用一張較大的圖片,但經過width height屬性來縮放這張圖片,這是很糟糕的方式,會加載更多的數據。

<img src="ocean.jpg" height="440" width="660" alt="Oceanview">

減小HTTP請求

與文件大小相似,一個網站的http請求數多是網站最大的性能缺陷。每當頁面與服務器創建了一個請求,頁面就會加載的更慢。有些請求必須在其餘請求完成後才能創建,過多的請求甚至能當掉服務器。

合併一樣類型的文件

合併同類型的文件多是一種最簡單的減小http請求的方法。特別是把全部的js文件,css文件各合併成一個文件。 合併這些文件以後,壓縮合並後的文件,能夠成功下降http請求。

<!-- Bad --> <link href="css/reset.css" rel="stylesheet"> <link href="css/base.css" rel="stylesheet"> <link href="css/site.css" rel="stylesheet"> <!-- Good --> <link href="css/styles.css" rel="stylesheet">

一般,頁面中的css文件應該優先加載,能夠放到head標籤裏面。而js文件應該最後加載,放到body的閉合標籤以前。這樣作的緣由是當頁面剩餘部分正在加載時,css能夠並行加載。而js恰好相反,加載時只能解析一個文件。這樣,在js加載的時候就會阻止其餘部分的加載。這裏有兩個例外:一是當js文件在頁面渲染後以異步方式加載,二是有些js文件與頁面渲染有關係,好比 html5 shiv( 讓ie瀏覽器支持html5標籤及設置樣式)。

使用Image Sprites(css精靈/雪碧圖)

ss精靈是指單張圖片,利用css控制做爲多個元素背景的技術。這個舉措,會減小使用多張圖片做爲背景圖所形成的http請求。

爲了建立包含一些背景圖片的精靈圖,常見的作法是把這些背景圖片排列到一張圖片裏。以後利用css設置這張精靈圖爲圖片背景,以後利用background-position屬性來移動圖片,從而顯示應該顯示的部分。

with the rest of the background image being hidden. 考慮情景:一個在元素下面不斷滑動的圖片,只會露出這個元素所圈定的部分。好比一個元素寬高16像素,若一張圖片在下面,僅僅會顯示一個16*16的區域,而區域外的圖片部分則不會顯示。

圖片精靈

這是一個文本編輯器的精靈圖,其外圍藍色輪廓顯示出圖片背景的參考位置。

咱們建立一個菜單,利用上面的精靈圖做爲span元素的背景圖片。以後利用class類名來改變精靈圖的位置,相應的圖片便會顯示出來。

HTML

<ul> <li><a href="#"><span class="bold">Bold Text</span></a></li> <li><a href="#"><span class="italic">Italicize Text</span></a></li> <li><a href="#"><span class="underline">Underline Text</span></a></li> <li><a href="#"><span class="size">Size Text</span></a></li> <li><a href="#"><span class="bullet">Bullet Text</span></a></li> <li><a href="#"><span class="number">Number Text</span></a></li> <li><a href="#"><span class="quote">Quote Text</span></a></li> <li><a href="#"><span class="left">Left Align Text</span></a></li> <li><a href="#"><span class="center">Center Align Text</span></a></li> <li><a href="#"><span class="right">Right Align Text</span></a></li> </ul>

CSS

li { float: left; list-style: none; margin: 0 2px; } li a { background: linear-gradient(#fff, #eee); border: 1px solid #ccc; border-radius: 3px; display: block; padding: 3px; } li a:hover { border-color: #999; } li span { background: url("sprite.png") 0 0 no-repeat; color: transparent; display: block; font: 0/0 a; height: 16px; width: 16px; } .italic { background-position: -16px 0; } .underline { background-position: -32px 0; } .size { background-position: -48px 0; } .bullet { background-position: -64px 0; } .number { background-position: -80px 0; } .quote { background-position: -96px 0; } .left { background-position: -112px 0; } .center { background-position: -128px 0; } .right { background-position: -144px 0; }

效果

圖片精靈

Image Data URI

此外,利用datauri的方法能夠代替css sprite雪碧圖,經過datauri,圖片能夠被編碼,從而包含在html與css內,直接被加載,消除了圖片的http請求。對於一些不會更新的小圖片來講Data URI很是有效,特別是html與css被緩存的時候。固然,datauri也會形成不少問題。因爲更新圖片須要從新編碼,這種方式很是難以維護。而且在老的瀏覽器裏,好比ie7如下,這種方式是無效的。

若是利用data uris能夠減小一些http請求,而html與css能夠獲得有效的緩存的話,這個措施是利大於弊的。能夠利用 converters pattern generators等工具來根據圖片建立datauris。在使用datauris前必定要再三確保生成的datauri代碼尺寸要比原圖小。

HTML

<img height="100" width="660" alt="Rigged Pattern" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA +m62AAAAPUlEQVQYV2NkQAN9x+z/F1kdZEQXRxGAKcKmGK4QXRKdD1aIyzpkcUZcimB uhMljOBrdEzAbiVIIUky0QgBkMCabd5DVAwAAAABJRU5ErkJggg==">

CSS

div {
  background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA
    +m62AAAAPUlEQVQYV2NkQAN9x+z/F1kdZEQXRxGAKcKmGK4QXRKdD1aIyzpkcUZcimB
    uhMljOBrdEzAbiVIIUky0QgBkMCabd5DVAwAAAABJRU5ErkJggg==") repeat;
}

效果

Image Data URI

文件緩存

緩存特定文件也能夠減小http請求,讓頁面加載的更快。當頁面第一次加載後,一些特定的文件會被緩存住。以後一段時間內,重複訪問這個頁面時,瀏覽器不須要再次請求相同的文件。這段時間取決於你,是根據你想讓特定類型的文件在客戶端保存的時間長短來決定的。

對於gzip壓縮過的文件來講,能夠經過htaccess文件 來設置expires頭(過時時間)用以緩存文件。 HTML5 Boilerplate再次走在了前列,他們的對.htaccess文件劃分出專門一塊區域來設置expires頭

圖片,視頻,網絡字體,以及一些常見的媒體類型通常都會緩存一個月,而css與js文件通常會緩存一年。Css或者其餘文件若是更新頻率超過一年一次的話,最好經過更改文件名進行版本控制,從而從新加載文件。此外,expires頭能夠改爲更小的時段。

ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"

把"access plus 1 year" 換成 "access plus 1 week",對於那些每週更新,但沒有利用文件名作版本控制的css與js文件是更適合的。關於有效的expires頭的資料能夠參考 mod_expires 語法

擴展閱讀:

  1. Best Practices for Speeding Up Your Web Site via Yahoo! Developer Network
  2. Rules for Faster-Loading Web Sites via Steve Sounders
  3. CSS Strategy Square-off via Viget Labs
  4. Writing Efficient CSS Selectors via Harry Roberts
  5. Minifying and Optimizing Files via Scott Hanselman
  6. HTML5 Boilerplate
  7. Data URIs via CSS-Tricks
  8. CSS DIY Organization
  9. Efficiently Rendering CSS
  10. 70 Expert Ideas For Better CSS Coding
  11. OOCSS——概念篇
  12. OOCSS——核心篇
  13. 面向對象的CSS(OOCSS)
  14. CSS架構

下一課

譯者手語:整個翻譯依照原文線路進行,並在翻譯過程略加了我的對技術的理解。若是翻譯有不對之處,還煩請同行朋友指點。謝謝!

關於玖玖

某創業團隊前端負責人,關注javascript應用與數據可視化。我的博客新浪微博Github,歡迎與同窗一塊兒共勉。

如需轉載煩請註明出處:

英文原文:http://learn.shayhowe.com/advanced-html-css/performance-organization

中文譯文:http://www.w3cplus.com/css/advanced-html-css-lesson1-performance-organization.html

相關文章
相關標籤/搜索