這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)CSS框架開發(fā)的示例分析,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都創(chuàng)新互聯(lián)是專業(yè)的湖南網(wǎng)站建設(shè)公司,湖南接單;提供成都網(wǎng)站建設(shè)、成都做網(wǎng)站,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行湖南網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
Philip Walton 在AppFolio擔(dān)任前端工程師,他在Santa Barbara on Rails的聚會上提出了CSS架構(gòu)和一些最佳實踐,并且在工作中一直沿用。
擅長CSS的Web開發(fā)人員不僅可以從視覺上復(fù)制實物原型,還可以用代碼進行完美的呈現(xiàn)。無需使用表格、盡可能少的使用圖片。如果你是個名副其實的高手,你可以快速把最新和最偉大的技術(shù)應(yīng)用到你的項目中,比如媒體查詢、過渡、濾鏡、轉(zhuǎn)換等。雖然這些都是一個真正的CSS高手所具備的,但CSS很少被人單獨拿出來討論,或者用它去評估某個人的技能。
有趣的是,我們很少這樣去評價其他語言。Rails開發(fā)人員并不會因為其代碼比較規(guī)范,就認(rèn)為他是一名優(yōu)秀的開發(fā)人員。這僅僅是個基準(zhǔn)。當(dāng)然,他的代碼得必須規(guī)范。另外,還需集合其他方面考慮,比如代碼是否可讀?是否容易修改或擴展……
這都是些很自然的問題,CSS和它們并沒有什么不同之處。今天的Web應(yīng)用程序要比以往更加龐大。一個缺乏深思熟慮的CSS架構(gòu)往往會削弱發(fā)展,是時候像評估其他語言那樣,來評估一下CSS架構(gòu)了,這些都不應(yīng)該放在“事后”考慮或者單單屬于設(shè)計師們的事情。
1.良好的CSS架構(gòu)目標(biāo)
在CSS社區(qū),很難提出某個最佳實踐已經(jīng)成為大家的普遍共識。純粹地從Hacker News的評論上判斷和開發(fā)者們對CSS Lint發(fā)布后的反應(yīng)來看,大多數(shù)人對基本的CSS東西是持反對意見的。所以,并不是為自己的最佳實踐奠定一套基本的論據(jù),而應(yīng)該確定真正的目標(biāo)。
好的CSS架構(gòu)目標(biāo)并不同于開發(fā)一個好的應(yīng)用程序,它必須是可預(yù)測、可重用、可維護和可伸縮的。
可預(yù)測
可預(yù)測意味著可以像預(yù)期的那樣規(guī)范自己的行為。當(dāng)你添加或者修改某個規(guī)則時,它并不會影響到?jīng)]有指定的部分。對于一個小網(wǎng)站來說,一些微乎其微的改變并不算什么。而對于擁有成千上萬個頁面的大網(wǎng)站來說,可預(yù)測卻是必須的。
可重用
CSS規(guī)則應(yīng)具備抽象和解耦性,這樣你就可以在現(xiàn)有的基礎(chǔ)上快速構(gòu)建新的組件,無需重新修改編碼模式。
可維護
當(dāng)把新組件放置到網(wǎng)站上,并且執(zhí)行添加、修改或者重新設(shè)計操作時,無需重構(gòu)現(xiàn)有CSS,并且新添加的X并不會打破原有頁面的Y組件。
可擴展
當(dāng)網(wǎng)站發(fā)展到一定規(guī)模后,都需要進行維護和擴展。可擴展的CSS意味著網(wǎng)站的CSS架構(gòu)可以由個人或者團隊輕易地管理,無需花費太多的學(xué)習(xí)成本。
2.常見的錯誤實踐
在實現(xiàn)良好的CSS架構(gòu)目標(biāo)之前,我們來看一些常見的錯誤做法,這對我們達成目標(biāo)是有好處的。
下面的這些例子雖然都可以很好的執(zhí)行,但卻會給你帶來很多煩惱,盡管我們的意圖和愿望都是美好的,但是這些開發(fā)模式會讓你頭疼。
幾乎在每個網(wǎng)站上,都會有一個特定的虛擬元素看起來與其他頁面是完全一樣的,然而只有一個頁面除外。當(dāng)面對這樣一種情況時,幾乎每個新手CSS開發(fā)人員(甚至是經(jīng)驗豐富的)都會以同樣的方式來修改。你應(yīng)該為該頁面找出些與眾不同之處(或者自己創(chuàng)建),然后再寫一個新規(guī)則去操作。
基于父組件來修改組件
CSS Code復(fù)制內(nèi)容到剪貼板
.widget {
background: yellow;
border: 1px solid black;
color: black;
width: 50%;
}
#sidebar .widget {
width: 200px;
}
body.homepage .widget {
background: white;
}
初看,這絕對是段無害的代碼,但讓我們來看看它是否達到了我們所設(shè)置的目標(biāo)。
首先,widget在examle是不可預(yù)見的。當(dāng)這些小部件出現(xiàn)在頁面兩側(cè)或者主頁面時,開發(fā)人員期望它們以某種特定的方式顯示出來,且又不失特色。另外,它也是不可重用或不可擴展的。
另外,它也比較難維護。一旦這個widget需要重新設(shè)計,那么你不得不修改其他幾個CSS樣式。想象一下,如果這段代碼是使用其他語言編寫的,它基本就是一個類定義,然后在代碼的另一部分使用該類定義并做出擴展。這直接違反了軟件開發(fā)的開放/閉合(open/close)原則。
軟件實體(類,模塊,函數(shù)等)應(yīng)對擴展開放,對修改閉合。
過于復(fù)雜的選擇器
偶爾,會有些文章介紹CSS選擇器對整個網(wǎng)站的展示起著非常重要的作用,并且宣稱無需使用任何類選擇器或者ID選擇器。
但伴隨著越深入的開發(fā),我越會遠(yuǎn)離這種復(fù)雜的選擇器。一個選擇器越復(fù)雜,與HTML就越耦合。依靠HTML標(biāo)簽和組合器可以保持HTML代碼干干凈凈,但卻讓CSS更加毛重和凌亂。
CSS Code復(fù)制內(nèi)容到剪貼板
#main-nav ul li ul li div { }
#content article h1:first-child { }
#sidebar > div > h4 + p { }
對上面代碼進行簡單的理解。第一個可能是對下拉菜單進行樣式化;第二個想說明文章的主標(biāo)題應(yīng)該與其他頁面的H1元素不同;最后一個表示在第一段的側(cè)邊欄區(qū)域添加一些額外的空間。
如果這個HTML是永遠(yuǎn)不變的,那就無可說之處,但這根本毫不現(xiàn)實。過于復(fù)雜的選擇器會讓人印象深刻,它可以讓HTML擺脫掉表面上的復(fù)雜,但對于實現(xiàn)良好的CSS架構(gòu)目標(biāo)卻毫無用處。
上面提到的例子都是不具備可預(yù)測性、可重用、可擴展和可維護這四大特性的。例如第一個選擇器(下來菜單)例子,如果一個外觀非常相似的下拉列表需要用在不同的頁面上,并且#main-nav并不屬于內(nèi)部元素,那么你是否需要重新設(shè)計?假設(shè)開發(fā)者想要修改第三個例子里div里面部分標(biāo)記,那么整個規(guī)則都會被打破。
過于通用的類名
當(dāng)創(chuàng)建可重用的設(shè)計組件時,在組件的類選擇器中覆蓋附件的子元素是很常見的現(xiàn)象。例如:
CSS Code復(fù)制內(nèi)容到剪貼板
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
In condimentum justo et est dapibus sit amet euismod ligula ornare.
Vivamus elementum accumsan dignissim.
.widget {}
.widget .title {}
.widget .contents {}
.widget .action {}
像.title、.contents、.action這些子元素類選擇器可以被安全地進行樣式命名,無需擔(dān)心這些樣式會蔓延到擁有相同類名的其他元素中。這是千真萬確的。但它并沒有阻止相同樣式類名稱會蔓延到這個組件上。
在一些大型項目上,像.title這樣的名稱很有可能會被用在另外一個頁面或者本身。如果這樣的情況發(fā)生,那么整個標(biāo)題部分明顯會和預(yù)期的不一樣。
過于通用的類選擇器名稱會導(dǎo)致許多不可預(yù)測的CSS樣式發(fā)生。
一個規(guī)則做太多事
有時,你要在網(wǎng)站的左上角區(qū)域做一個20pixels的可視化組件。
CSS Code復(fù)制內(nèi)容到剪貼板
.widget {
position: absolute;
top: 20px;
left: 20px;
background-color: red;
font-size: 1.5em;
text-transform: uppercase;
}
下面,你需要在網(wǎng)站的其他區(qū)域使用該組件,那么上面的這個代碼明顯是錯誤的,不可重用的。
問題的關(guān)鍵是你讓.widget這個選擇器做的事情太多,不僅對該組件的位置進行了規(guī)定,還對它的外觀和感覺方面進行了樣式。外觀和感覺可以通用,而位置是不可以的。有時候,把它們整合起來使用反而會大打折扣。
雖然這些看起來并無害處,對一些缺乏經(jīng)驗的CSS程序員來說,復(fù)制和粘貼已經(jīng)成為一種習(xí)慣。如果一個新團隊需要一個特定組件,比如.infobox,他們會嘗試使用這個類選擇器。但如果該信息框沒有按照期望的那樣,在每個需要的地方正確顯示出來。這時,你認(rèn)為他們會怎么做?以我的經(jīng)驗來看,他們會打破可重用這一規(guī)則,相反,他們會簡單地把這些代碼復(fù)制粘貼到每個需要的地方。做些不必要的重復(fù)工作。
3.原因
上面列舉的這些常規(guī)錯誤實踐都有一個相似性,CSS樣式承擔(dān)過多。
對這樣的說法你會感到奇怪,畢竟,它是一個樣式表,難道不應(yīng)該承擔(dān)大多數(shù)(如果不是全部)的樣式嗎?那不正是我們想要的嗎?
的確。但是通常來講,事情并沒有那么簡單。內(nèi)容與表現(xiàn)(presentation)相分離是件好事,但CSS從HTML中獨立出來并不意味著內(nèi)容也需要從表現(xiàn)中分離。換句話說,如果CSS請求深入分析HTML架構(gòu),那么從HTML中分拆所有的顯示代碼并不一定會實現(xiàn)所有的目標(biāo)。
此外,HTML很少會只包含內(nèi)容,也表示整體框架。通常,架構(gòu)是會包含container元素,允許CSS隔離一些固定元素。即使沒有表象類(presentational classes),也能混合HTML清晰地把內(nèi)容展示出來。
我相信,鑒于當(dāng)前的HTML和CSS狀態(tài),把HTML和CSS明智地結(jié)合起來,當(dāng)做表現(xiàn)層是非常需要的。而通過模板和局部模板(partials)也可以把內(nèi)容層進行分離。
4.解決方案。
如果把HTML和CSS結(jié)合起來,作為一個Web應(yīng)用程序的表現(xiàn)層,那么它們需要采取一些方式更好地促進優(yōu)秀CSS架構(gòu)的形成。
最好的方法是CSS中盡可能少的包含HTML架構(gòu)。CSS則是應(yīng)該定義元素的視覺效果,無論該視覺元素在哪里。如果有一些特定的組件需要在不同的場合顯示不同的效果,那么應(yīng)該賦予不同的名稱。例如,CSS通過.button類選擇器定義了一個按鈕組件。如果HTML想要一個特定的元素看起來像按鈕,那么就可以使用.button。如果這里有特殊要求,這里的按鈕與其他的有所不同(有可能更大和寬些),那么CSS需要定義一個新的類,HTML可以使用新的類來賦予該元素新的視覺效果。
CSS賦予元素的外在特征,HTML在頁面上進行調(diào)用。更少的CSS能被更多的HTML架構(gòu)調(diào)用是最好的。
準(zhǔn)確地在HTML中聲明元素不僅可以清晰表達設(shè)計意圖,其他開發(fā)者也可以清晰地查看標(biāo)記并且知道元素將呈現(xiàn)的樣子。如果沒有這種實踐,它很難區(qū)分一個元素的外觀設(shè)置是有意或無意的,這樣很容易導(dǎo)致團隊混亂。
在標(biāo)記中填入大量的類(classes)是種常見缺陷,這樣做往往需要花費額外的精力。一個CSS樣式可以給一個特定組件引用上千次。那么,為了在標(biāo)記里面進行顯示聲明,就真的值得去重復(fù)編寫這樣的類嗎?
雖然這種擔(dān)心是有效的,但它可能會產(chǎn)生誤導(dǎo)。言下之意就是無論你在CSS中使用一個父選擇器還是親手編寫上千個Class,這里都會有些額外的選擇。在Rails或者其他框架里查看同級別抽象很大程度上可以在HTML中保持很好的視覺外觀,并且無需在類中一遍又一遍地編寫相同的類。
5.最佳實踐。
針對上面的種種錯誤,我進行了很好地總結(jié),并且根據(jù)自身經(jīng)驗提出了一些建議,希望它們能幫助您更好地實現(xiàn)良好的CSS架構(gòu)目標(biāo)。
專注
確保選擇器對一些元素不進行無關(guān)樣式的最好方法是不給它們機會。例如像#main-nav ul li ul li div這樣的選擇器可能很容易地應(yīng)用于不想要的元素上。另一方面,像.subnav這樣的選擇器就不會給它們?nèi)魏螜C會。把類選擇器直接應(yīng)用于你想要的元素上是最好的方式,并且可以保持元素的可預(yù)測性。
CSS Code復(fù)制內(nèi)容到剪貼板
/* Grenade */
#main-nav ul li ul { }
/* Sniper Rifle */
.subnav { }
模塊化
一個組織結(jié)構(gòu)良好的組件層可以幫助解決HTML架構(gòu)與CSS那種松散的耦合性。此外,CSS組件本身應(yīng)該是模塊化的。組件應(yīng)該知道如何進行樣式和更好地工作,但是關(guān)于布局、定位以及它們與周圍元素的關(guān)系不應(yīng)該做太多的假設(shè)。
一般而言,CSS要定義的應(yīng)該是組件的外觀,而不是布局或者位置。同樣在使用background、color和font這些屬性時也要遵循原則使用。
布局和位置應(yīng)當(dāng)由一個單獨的布局類或者單獨的容器元素構(gòu)成(請記住,有效地把內(nèi)容與展示進行分離其實就是把內(nèi)容與容器進行分離)。
給類進行命名空間
我們已經(jīng)檢查出為什么父選擇器不能在封閉和防止交叉樣式污染上面發(fā)揮100%的功效。而一個更好的解決方案就是在類上應(yīng)用命名空間。如果一個元素是可視化組件的一員,那么該元素的每個子元素都應(yīng)該使用基于命名空間的組件。
CSS Code復(fù)制內(nèi)容到剪貼板
/* High risk of style cross-contamination */
.widget { }
.widget .title { }
/* Low risk of style cross-contamination */
.widget { }
.widget-title { }
給類進行命名空間可以保持組件獨立性和模塊化。它可以把現(xiàn)有類沖突降至最小并且減少子元素的一些特殊要求。
創(chuàng)建修飾符類來擴展組件
當(dāng)一個現(xiàn)有組件需要在一個特定的語境中有所不同時,可以創(chuàng)建一個修飾符類(modifier class)來擴展它。
CSS Code復(fù)制內(nèi)容到剪貼板
/* Bad */
.widget { }
#sidebar .widget { }
/* Good */
.widget { }
.widget-sidebar { }
正如我們看到的,基于父元素的缺點對組件進行修改,需要重申:一個修飾符類可以在任何地方使用?;谖恢玫母采w只能被用在一個特定的位置,修飾符類也可以根據(jù)需要被多次使用。顯然,修飾符類是符合HTML開發(fā)者需求的。
把CSS組織成邏輯結(jié)構(gòu)
Jonathan Snook在其非常優(yōu)秀的《SMACSS》書中提到,CSS可以被分成四個不同的類:基礎(chǔ)(base)、布局(layout)、模塊(modules)和狀態(tài)(state)?;A(chǔ)包括了復(fù)位原則和元素缺省值;布局是對站點范圍內(nèi)的元素進行定位以及像網(wǎng)格系統(tǒng)那樣作為一種通用布局助手;模塊即是可重用的視覺元素;狀態(tài)即指樣式,可以通過JavaScript進行開啟或關(guān)閉。
組件是一個獨立的視覺元素。模板在另一方面則是構(gòu)建塊。模板很少獨自站在自己的角度去描述視覺和感覺,相反,它們是單一的、可重用的模式,可以放在一起形成組件。
為了提供更詳細(xì)的例子,一個組件可能就是一個模式對話框。該模式可能在頭部包含漸變的網(wǎng)站簽名、或者在周圍會有陰影、在右上角會有關(guān)閉按鈕、位置固定在垂直與水平線中間。這四個模式可能被網(wǎng)站重復(fù)多次使用,所以在每次使用的時候,你都很少會想到重新編碼與設(shè)計。這些所有的模板即形成了一個模塊組件。
因樣式和風(fēng)格使用類
有過大型網(wǎng)站建設(shè)的人可能有個這樣的經(jīng)驗,一個擁有類的HTML元素可能完全不知道其用途。你想刪除它,但是又猶豫不決,因為它的作用你可能還未意識到。一旦這樣的事情一遍又一遍發(fā)生的時候,隨著時間的推移,項目中將會有越來越多這樣的類,只因為團隊成員都不敢刪除。
在Web前端開發(fā)中,類承擔(dān)了太多的責(zé)任,因此才會產(chǎn)生這樣的問題。樣式化HTML元素、扮演著JavaScript hook角色、功能檢測、自動化測試等。當(dāng)這么多應(yīng)用程序在使用類時,讓你從HTML中刪除它們將會變的非常艱難。
然而,使用一些成熟的約定(慣例)即可完全避免這種問題。當(dāng)在HTML中看到一個類時,你應(yīng)該立即明白它的目的。我建議在前面使用前綴,例如用于JavaScript的在前面加.js,表示Modernizr classes可以在前面加.supports,沒有加前綴的即用于表示樣式。
這樣來發(fā)現(xiàn)未使用的類和從HTML中移除它們將會變得非常簡單。你甚至可以自動完成這一個過程,在JavaScript中通過交叉引用HTML中的document.styleSheets對象。如果在document.styleSheets中沒有發(fā)現(xiàn)該類,即可安全移除。
一般來說,最佳做法是把內(nèi)容與演示相分離,另外把功能分離開來也同樣重要。使用樣式類像JavaScript hook在某種程度上可以加深CSS與JavaScript之間的耦合,但在不打破功能性的前提下很難或者根本不可能更改外觀。
有邏輯的命名類
大多數(shù)寫CSS的人喜歡使用連字符來分隔命名詞,但連字符并不足以區(qū)分不同類型之間的類。
Nicolas Gallagher最近針對遇到的問題寫了一個解決方案,并且取得了巨大的成功(略有改動),為了說明命名約定,可以考慮以下格式:
CSS Code復(fù)制內(nèi)容到剪貼板
/* A component */
.button-group { }
/* A component modifier (modifying .button) */
.button-primary { }
/* A component sub-object (lives within .button) */
.button-icon { }
/* Is this a component class or a layout class? */
.header { }
從上述類中可以發(fā)現(xiàn)其很難正確區(qū)分類型規(guī)則。這不但會困惑,而且連自動測試CSS和HTML也變的很難。一個結(jié)構(gòu)化的命名約定應(yīng)該是初看就能夠知道其類名與其他類之間的關(guān)系,并且知道它出現(xiàn)在HTML中的位置——使命名更加簡單和容易測試。
CSS Code復(fù)制內(nèi)容到剪貼板
/* Templates Rules (using Sass placeholders) */
%template-name
%template-name--modifier-name
%template-name__sub-object
%template-name__sub-object--modifier-name
/* Component Rules */
.component-name
.component-name--modifier-name
.component-name__sub-object
.component-name__sub-object--modifier-name
/* Layout Rules */
.l-layout-method
.grid
/* State Rules */
.is-state-type
/* Non-styled JavaScript Hooks */
.js-action-name
重做第一個例子:
CSS Code復(fù)制內(nèi)容到剪貼板
/* A component */
.button-group { }
/* A component modifier (modifying .button) */
.button--primary { }
/* A component sub-object (lives within .button) */
.button__icon { }
/* A layout class */
.l-header { }
6.工具
維護一個高效且組織良好的CSS架構(gòu)是非常困難的,尤其是在大型團隊中。下面向大家推薦幾款很好的工具來幫你管理網(wǎng)站CSS架構(gòu)。
CSS Preprocessor
CSS預(yù)處理器采用PHP5編寫,有預(yù)處理器的常見功能,可以幫你快速編寫CSS。另外有些號稱“功能”的預(yù)處理器實際上并不會對CSS架構(gòu)產(chǎn)生良好作用。下面我提供一個列表,在使用時一定要避免:
● 切勿純粹為了組織代碼來嵌套規(guī)則。只有當(dāng)輸出你真正想要的CSS時才可以。
●在無需傳遞參數(shù)的時候切勿使用mixin,不帶參數(shù)的mixin更適合用作模板,易擴展。
●切勿在選擇器上使用@extend,它不是個單一的類。從設(shè)計角度來看是毫無意義的,它會膨脹編譯過的CSS。
●在運用組件修飾符規(guī)則時,切勿使用@extend UI組件,這樣會失去基礎(chǔ)鏈。
@extend和%placeholder是預(yù)處理器里面非常好的兩個功能。它們可以幫你輕松管理CSS抽象并且無需添加bloat和大量的基類到CSS和HTML里,否則將會很難管理。
當(dāng)你初次使用@extend時,常會與修飾符類一起使用,例如:
CSS Code復(fù)制內(nèi)容到剪貼板
.button {
/* button styles */
}
/* Bad */
.button--primary {
@extend .button;
/* modification styles */
}
這樣做會讓你在HTML中失去繼承鏈。很難使用JavaScript選擇所有的按鈕實例。
作為一般規(guī)則,很少去擴展UI組件或者在知道類型后做些什么。這是區(qū)分模板和組件的一種方式,模板無需參與到應(yīng)用程序的邏輯,并且可以使用預(yù)處理器進行安全擴展。
下面是一個引用上面的模式例子:
CSS Code復(fù)制內(nèi)容到剪貼板
.modal {
@extend %dialog;
@extend %drop-shadow;
@extend %statically-centered;
/* other modal styles */
}
.modal__close {
@extend %dialog__close;
/* other close button styles */
}
.modal__header {
@extend %background-gradient;
/* other modal header styles */
}
CSS Lint
CSS Lint是由Nicole Sullivan和Nicholas Zakas編寫的一款代碼質(zhì)量檢測工具,幫助CSS開發(fā)人員寫出更好的代碼。他們的網(wǎng)站上是這樣介紹CSS Lint的:
CSS Lint是一個用來幫你找出CSS代碼中問題的工具,它可做基本的語法檢查以及使用一套預(yù)設(shè)的規(guī)則來檢查代碼中的問題,規(guī)則是可以擴展的。
使用CSS Lint建議:
1.不要在選擇器中出現(xiàn)ID。
2.在多部分規(guī)則中,不要使用非語義(non-semantic)類型選擇器,例如DIV、SPAN等。
3.在一個選擇器中使用的連接符(combinator)不要超過2個。
4.任何類名都不要以“js-”開始。
5.如果在非“I-”前綴規(guī)則里經(jīng)常使用布局和定位應(yīng)給予警告
6.如果一個類定義后被重新定義成子類,也應(yīng)給予警告。
總結(jié)
CSS不僅僅是視覺設(shè)計,也不要因為你編寫CSS就隨便拋出編程的最佳實踐。像OOP、DRY、打開/閉合、與內(nèi)容分離等這些規(guī)則應(yīng)該應(yīng)用到CSS里面。無論你如何組織代碼,都要確保方法真正幫助到你,并且使你的開發(fā)更加容易和可維護的。
上述就是小編為大家分享的CSS框架開發(fā)的示例分析了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。