本文由大漠根據Krasimir Tsonev的《Starting to Write CSS》所譯,整個譯文帶有咱們本身的理解與思想,若是譯得很差或不對之處還請同行朋友指點。如需轉載此譯文,需註明英文出處:http://davidwalsh.name/starting-css,以及做者相關信息javascript
——做者:Krasimir Tsonevphp
——譯者:大漠css
你不要以爲CSS沒什麼重要可言?最近幾年他成爲一個熱門的話題,不少人都在討論他。CSS並非一個簡單的事情,前端開發者可使用他將頁面製做的更佳漂亮。看得更遠一些,咱們更關心的是網站的性能以及如何製做出更好的網站。在本文中,我想分享我最近幾個月的學到的有關於CSS編碼的知識。做爲一個程序員,我真正感興趣的事情是框架(Architectural
)部分。我以爲寫CSS應該須要去改變,爲此我深挖了不少知識。我搜索了好的程序、工做流和原則。這篇文章將帶領你們和CSS一塊兒旅行,不少人都說寫CSS並非編程,我就不一樣意,我說寫CSS一樣是有趣的,富有挑戰性的。html
讓咱們一塊兒面對吧,在世界上寫CSS並非一件好笑的事情。CSS預處理器看起來就像CSS,但他更像一個魔術師同樣,使用一些魔法會產生有效的CSS代碼。這讓你的樣多和瀏覽器之間新增長了一層,這樣不是更加的糟糕嗎?看上去是這樣,但事實不是這樣的,由於CSS預處理器提供了一些真正有用的特性。前端
我認爲最有價值的東西是鏈接你的文件。我相信,你知道使用@import
來引用你的.css
文件,告訴瀏覽器獲取這個文件。這樣作,瀏覽器須要增長一個請求,這樣有點麻煩,由於你可能有不少個這樣的文件。增長額外的請求,使你的程序性能變得更低。若是您使用CSS預處理器語言,這個問題將不會存在。他們只會編譯你樣式文件中單個.css
文件。java
LESS和Sass是最主要的兩個CSS預處理器。咱們都支持擴展。雖然他們的工做方式略有不一樣,但他們的想法是同樣的。你能夠作一個基本的類(一般稱爲mixin
)和一羣屬性,而後在另外一個選擇器導入這些屬性,如:node
// less .bordered(@color: #000) { border: dotted 2px @color; } .header { .bordered; } .footer { .bordered(#BADA55); } // 編譯出來的CSS .header { border: dotted 2px #000000; } .footer { border: dotted 2px #bada55; }
這裏的問題是,若是你沒有定義一個參數的mixin
,例如剛纔的示例:git
.bordered { border: dotted 2px #000; }
這是最後編譯的CSS文件,不管你是否使用都沒有任何關係。由於他是一個有效的選擇器。在Sass中咱們能夠作得更靈活一些。他有混合(mixins
)、擴展(extends
)和佔位選擇器(placeholders
)(若是您想看到他們之間的區別,我強烈建議您閱讀這篇文章)。接下來咱們簡單看看Sass是如何工做和編譯的:程序員
// sass @mixin bordered($color: #000) { border: dotted 2px $color; } .header { @include bordered; } .footer { @include bordered(#BADA55); } //編譯的CSS .header { border: dotted 2px black; } .footer { border: dotted 2px #bada55; }
它看起來和前面幾乎相同,但若是咱們秋看第二個placeholder
的用例:github
// sass %bordered { border: dotted 2px #000; } .header { @extend %bordered; } .footer { @extend %bordered; } // 編譯的CSS .header, .footer { border: dotted 2px #000; }
這個有兩個優點,首先不會編譯出.bordered
類名,其次會使用組合選擇器,合併相同的樣式,使代碼變得更加簡潔。
LESS和Sass都支持變量,你能夠調用這些變量,將將他們做爲屬性的值:
// sass $brand-color: #009f0A; ... h1 { color: $brand-color; }
這是一個很好的特性,由於你能夠儲存一些重要的東西,好比說顏色或者網格的寬度,將他們存放在同一個地方,若是你須要修改一些不常常改動的代碼,會變得很是的簡便。
另外一個好處理,可使用變量的插值,以下面演示的方法:
// sass @mixin border($side) { border-#{$side}: solid 1px #000; } .header { @include border("left"); } // 編譯的CSS .header { border-left: solid 1px #000; }
.less
或.sass
文件,可是輸出是什麼很是重要。你可能有寫得很好的Sass代碼,但這並不意味着,你最終會有很好的CSS代碼。可能會有一些特異性的問題,因此須要按期檢測編譯的版本。好的,我找到了一個新的好玩工具。這個預處理器能夠節省大量的時間,但他不能爲你寫出好的結構。首先,我開始考慮是一個命名約定,讓咱們來看如下的HTML標籤:
<header class="site-header"> <div class="logo"></div> <div class="navigation"></div> </header>
可能會寫出對應的樣式:
.site-header { ... } .logo { ... } .navigation { ... }
這樣的樣式能正常的工做,但它有一個問題——閱讀CSS,讓人難於理解。例如,logo
是屬於header
部分的,你可能有另外一個logo
要放在頁腳footer
處。那麼將添加一個後代選擇器來控制:
.site-header .logo { ... }
可是使用這些選擇器並非很好的主意,由於它始終須要依賴於特定的標記和結構。一旦你把logo
移到<header>
外面,樣式將會丟失。另一種作法是給logo
添加一個site-header
,給其從新命名:
.site-header-logo { ... }
很棒了,本身就是說明,但它並不能運用於全部狀況之下。例如,我想在12的聖誕節使用一個聖誕節版本的logo
。因此,我不能寫:
.site-header-logo-xmas { ... }
由於個人邏輯是,寫一個選擇器要像嵌套HTML標籤同樣匹配。
BEM可能解決這樣的狀況。這意味着塊(Block)、元素(Element)和修改器(Modifier)和一些建立規則,你能夠遵循這些規則。使用BEM,咱們的小例將變成:
.site-header { ... } /* block */ .site-header__logo { ... } /* element */ .site-header__logo--xmas { ... } /* modifier */ .site-header__navigation { ... } /* element */
也就是說site-header
是咱們的塊。那麼logo
和navigation
是這個塊的元素,聖誕版本的logo
是修飾符。也許它看起來簡單,可是它真的很強大。一旦你開始使用它,會發現他能讓你的結構更加的優秀。固然也有反對的理由,那就是由於其語法。是的,或許看起來有點醜,但爲了有一個好的結構,我會準備爲此作出犧牲。(更好的閱讀請點這和這)。
自從我發現BEM,我就開始在思考如何正確的使用個人類名。也許,個人第一件事情要讀一篇關於面向對象的CSS。面向對象編程添加了一些抽像的概念,CSS也支持這樣的概念。若是你使用了CSS預處理器,你或多或少知道一些。作爲一個編寫代碼的人,我發現這個概念離我平時編程很近,拿JavaScript爲例,有兩個主要原則:
咱們用下面的例子來進行介紹:
.header { background: #BADA55; color: #000; width: 960px; margin: 0 auto; } .footer { background: #BADA55; text-align: center; color: #000; padding-top: 20px; }
其中有一些樣式是重複的,咱們能夠考慮在另外一個類中提取這些相同的樣式:
.colors-skin { background: #BADA55; color: #000; } .header { width: 960px; margin: 0 auto; } .footer { text-align: center; padding-top: 20px; }
因此咱們使用colors-skin
作爲一個對象,用來擴展。這樣HTML模板修改爲像這樣:
<div class="header colors-skin"> ... </div> <div class="colors-skin"> ... </div> <div class="footer colors-skin"> ... </div>
這樣作有幾個好處:
這裏的想法是,每一個元素應該有相同的樣式,無論他放在何處。因此,你應該儘可能避免使用像下面演示的選擇器:
.header .social-widget { width: 250px; }
若是你把.social-widget
移動.header
容器的外面,那麼.social-widget
的寬度就變了。尤爲是用在頁面上的組件。這也是我鼓勵CSS模塊化以及我強烈建議採用更多的時間去嘗試。就我我的而言,如下的原則會將CSS寫得更好。
若是你在GitHub上打開OOCSS庫你能夠看到一個框架。是的,這個框架使用了面向對象的概念,他的CSS有不少很優秀的現成組件。很長一段時間我並不喜歡框架。若是你有在工做使用框架,你會發現他分爲兩個部分。事實上,你使用框架處理一些事情,你必須遵照他的規則。不過我更喜歡使用一些微小的框架。固然我不是說我得從新去造輪子,但我老是試圖去尋找一種平衡。一般現成的解決方案致使系統的混亂和複雜。我建議是爲必定的目的創建一個特定的東西。若是你試圖去覆蓋一些東西,你老是想到框架中的東西。
但事,我強烈建議你去查尋一個OOCSS框架。這是一個獨特的知識塊,也許它將適合用在你須要的地方。最先是由Nicole Sullivan提出這樣的一個概念。若是你對OOCSS有什麼意向或者想法,可到這裏參加討論。
另外一個流行的概念是SMACSS。SMACSS表明可伸縮的和是模塊化的CSS結構體系。Jonathan Snook爲CSS開發人員介紹了相似於這樣的樣式指南。爲了單獨的應用程序將其分爲如下幾類:
clearfix
header
和sidebar
我沒有使用SMACSS的任何經驗,便它是很是受歡迎,實際上也能促進你有更好的想法。這比一個框架的概念更強。因此,你不須要遵循任何嚴格的規則、類或者組件。
知道了OOCSS和SMACSS後,請容許我找一個恰當的比喻,請快速登陸這個頁面。這裏展現了一個偉大的原子設計概念。它的做者是Brad Frost,衆所周知,他是一位有名的Web開發人員,致力於響應式設計和移動端開發。
這個想法是很是有趣的。如下是一些術語,咱們能夠說,物質的基本單位是原子。Brad Frost說咱們的頁面是用移動的原子構建,一個原子能夠是:
<label>Search the site</label>
或者
<input type="text" placeholder="enter keyword" />
也就是說原子是包括了一些基本樣式的DOM元素。如顏色、字體大小或者過渡動畫。後來這些部分能夠結合成分子,例如:
<form> <label>Search the site</label> <input type="text" placeholder="enter keyword" /> <input type="submit" value="search" /> </form>
因此表單元素包含了幾個原子。這樣抽象帶來的靈活性,由於咱們可使用相同的原子來構建另外一個分子。這樣一來,咱們在不一樣的上下文中能夠重用相同的形式:
Brad Frost並無中止。生特體是構建分子的東西,遵循一樣的方法,咱們能夠編寫如下的結構,並將其稱爲有機體:
<header> <div class="logo"> </div> <nav> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Contacts</a></li> </ul> </nav> <form> <label>Search the site</label> <input type="text" placeholder="enter keyword" /> <input type="submit" value="search" /> </form> </header>
第二件事是模板的概念。他們不是直接相關的化學反應,但被放入了Web的上下文。一旦咱們開始結合不一樣的生物構建咱們的模板。後來這些模板形式就是咱們最後獲得的頁面。
你可能已經使用相似的方法來構建應用程序。然而,命名的東西以一種合理的主式帶來良好的結構。在開發中,你和你的隊友會有不少事情須要去弄明白。分離的原子和分子是很重要的部分,由於它提升了工做效率和讓你更好的維護您的Web應用程序。
兩個月前,我寫了一篇文章,是有關於Organic的,他是一個用JavaScript寫的一個偉大的小框架。它更像是一種設計模式,我我的很是喜歡。我甚至在好幾個項目中使用了它,而且一切都很順利。若是你有興趣的話,我強烈推薦您閱讀這篇文章。
當我閱讀了Brad Frost的文章,我就已經有了相似於的概念,由於我知道Organic。Brad作的很是的棒,可是我決定更深刻的去了解,或嘗試本身在基於原子設計概念的基礎上寫一個小型的框架。我最終選擇了Sass做爲預處理器和在Github上建立了一庫organic-css。
讓我勻先從框架最小的一部分開始——原子。維基百科是這樣定義的,原子是物質的基本單位。在CSS中,我認爲它是一個屬性和一個屬性值,例如:
margin-top: 24px;
僅僅爲了寫樣式添加原子而直接添加類名,這並非我想要的,若是有一個這樣的類型:
body { margin-top: 24px; } header { margin-top: 24px; }
預處理器將會失去他本身做用,由於我想要的結果是這樣的:
body, header { margin-top: 24px; }
在Sass中可使用placeholders
的功能,例如:
%margin-top-24 { margin-top: 24px; } body { @extend %margin-top-24; } header { @extend %margin-top-24; }
因此我不得不使用placeholder
。這也意味着,我必需要定義不少placeholders
,才能使用。在那一刻,我決定,這個框架將只包含原子。也許有一些分子和通用的函數,例如reset.css
、網格的定義等等。我想寫點東西,做爲一個基礎的CSS開發。也許我會看到項目中的一些模式,將其放在覈心處,做爲一個開始,並保持乾淨和簡單。
事情變得更加的一致化,我建立了一個mixin
做爲一個原子。如這個例子:
@include define-atom("block") { display: block; } @include define-atom("font-family") { font-family: Georgia; }
使用這種方法,我建立了一個原子羣,而且能夠很容易的適合用於每個項目。你能夠點擊查看。我而且拿其餘的框架做爲對比,讓我更好的去實踐,從中學到不少東西。還能夠製做一個mixin
分子,將原子相結合在一塊兒:
@mixin header { // <- molecule called 'header' @include atoms(( block, clearfix, font-family )); }
分子是一個DOM元素須要樣式,但他沒有子元素。或者他有子元素,便也不會直接鏈接到它。如<img src="logo.jpg" />
,多是一個分子。若是你很難在你的頁面識別這些分子,只須要想到什麼是由原子構建就行。有些元素也有多是構建其餘分子的原子。如:
@mixin login-box { @include atoms(( block, font-size-20, margin-top-23, bold )); }
咱們將面對一些頗有趣的事。好比說咱們的body
標籤。他是什麼呢?它是一個分子或其餘什麼嗎?固然,這須要一些樣式,但通常在原子中包含其餘分子。它應該是其餘東西。個人結論是,CSS應該是主要部分,也就是說,若是body
樣式須要幾個原子,那麼他就是一個分子。這也就意味着,從理論上講,我不該該附加任何其餘的分子給它。這看起來有點不切實際,但在大多數狀況下,會讓你使用不一樣的選擇器,這將是一個好的發展跡象。
一旦你認識到這個DOM元素是分子,那麼你能夠將其看到是一個細胞器。例如,典型的表單元素是一個很好的細胞器例子,他包含像label
、input
和textarea
這樣的分子。
.login-form { @include label; @include input; @include textarea; }
這些也許是框軻中的一部分,它緊密的鏈接到當前應用程序中。原子和分子可能在不一樣項目之間移動,而細胞器是不可能會移動的。
不少時候你可能想把幾個別的東西放在一塊兒,這樣細胞器變得更加抽象:
Atom → Molecule → Organelle → Cell → Tissue → Organ → Sys → Organism
這將面對一個選擇問題,你將如何構建你的CSS。我之前只在一個項目中使用OrganicCSS,到目前爲止,我還能夠說他是清晰的。我把不一樣的元素放在他們本身的目錄中和按他們的名命名,這樣我能夠很容易的找到他們,並作相應的處理。例如,若是有一個細胞器稱爲header
,我只須要將其修改成o-header
。後來,讓我讀到HTML標記,我就能夠看到該元素的CSS樣式就在細胞器文件夾中。
這是一個頗有趣的旅程。我不知道我未來會不會使用OrganicCSS,但這並非最重要的部分。我能從中學到東西纔是最重要的。我知道我必須改變咱們的CSS開發過程,我作到了。我認爲咱們應該多談談CSS的框架。你能夠看到咱們有不少好的資源。咱們必須找到他們,學習他們作什麼以及如何工做。只有這樣咱們才能夠決定是否使用他們。更好的是,當你看到整個圖片你能夠創造一些更適合你的需求。
特別聲明:本文有不少概念也是初次接觸,就對此文進行翻譯,若是有理解錯語的地方,但願不會給您帶來誤解,同時更但願這譯文能改變你對CSS的構建方式,從而找出更適合您或您團隊使用CSS的最佳方式。最後但願更多的同行朋友能指正文中不正確的地方和分享相關的資源(^_^)
譯者手語:整個翻譯依照原文線路進行,並在翻譯過程略加了我的對技術的理解。若是翻譯有不對之處,還煩請同行朋友指點。謝謝!
如需轉載煩請註明出處: