曾有人調侃,設計模式是工程師用於跟別人顯擺的,顯得高大上;也曾有人這麼說,不是設計模式沒用,是你尚未到能懂它,會用它的時候。css
先來看一下比較官方的解釋:「設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的;設計模式使代碼編制真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構同樣。」html
今天咱們來聊聊CSS的設計模式。前端
設計模式,這個詞彙咱們常見,幾乎全部的編程語言都會有幾套,但深刻研究的人很少,緣由以下:編程
一、彷佛沒有太大必要性去強調它,有問題了改一下或者按團隊規範來就行;設計模式
二、不去使用一些既有的模式也無傷大雅;瀏覽器
三、很多人所接觸的業務量級尚未達到須要規劃和組織的程度,光寫佈局,寫特效,照顧兼容,就夠喝一壺的了,沒有意識去思考一些方法論的問題。編程語言
固然,這三者都是我經歷過的,相信你也是~ide
咱們都會長大,都會慢慢的作更多、更大、更復雜的項目,這個時候,就須要自上而下,全流程的去思考一些問題。後臺不說,只講前端,好比:風格的制定、色調、模塊、佈局方式、交互方式、邏輯等等,若是再加上團隊合做,若再沒有一個規劃的話,要不了多久,那些看起來沒問題的代碼,就會暴露出各類問題,模塊命名、類的命名、文件的組織、共用模塊的提取、代碼的複用、可讀性、擴展性、維護性。它們看起來只是一些簡單的小動做,卻須要你看得更遠,避免未來出問題須要付出更大的代價,甚至被迫整個項目重構,可謂,功在當代,利在千秋~組件化
既然要對CSS進行設計,那麼確定是它自己存在一些問題或者缺陷,其中,一個最明顯的就是,它的任何一個規則,都是全局性的聲明,會對引入它的頁面當中全部相關元素起做用,無論那是否是你想要的。而獨立及可組合的模塊是一個可維護系統的關鍵所在。下面,咱們就從多個層面來探討一下,到底該怎樣寫CSS,纔是更科學的。佈局
分
咱們剛開始學習寫字的時候,是不會去考慮,寫出來的某句話好很差,文章結構合適不合適,由於咱們是意識不到的。寫代碼也同樣,剛開始,咱們只是去定義規則,能用對了屬性,語法正確,把頁面實現出來了,就好。慢慢地,就會發現,頁面也是有結構的,咱們按照頁面的結構去組織代碼,會不會更好?好比,分紅頭部、導航、側邊欄、banner區、主內容區、底部等。
然而這樣貌似仍是不夠,由於還有一些東西,複用度是很高的,又很差把它歸爲任何一個固有模塊,好比:麪包屑、分頁、彈窗等,它們不適合被放到某一個固有模塊的代碼中,就能夠單獨的分出一段專屬的css和js,或許,這就是組件化的由來~
拆
在分了以後,咱們的代碼看起來已經比以前好不少了,組織清晰,維護性大幅提升,可是,好像仍是不夠,咱們會發現另一些東西,很細小,但複用度也很高,它們一樣不適合被放到模塊中去,好比,邊框、背景、圖標、字體、邊距、佈局方式等等。若是咱們在每一個須要它們的地方,都定義一次,它們會被重複不少次,顯然,這背離好的實踐,會形成代碼冗餘和維護困難。因此,咱們須要「拆」。拆過以後會怎樣?咱們想在哪裏用能夠直接加,須要改的時候統一改。
排
通過了「分」、「拆」,咱們的代碼結構已經十分清晰,各個內容模塊,功能模塊,UI模塊都乖巧的等待召喚,那麼還差什麼?是的,還差有序的組織,分類清晰以後,還須要排列有序,從不一樣緯度去考量,咱們總能精益求精。舉個栗子,咱們可能會看到像這樣:
@import "mod_reset.css"; @import "ico_sprite.css"; @import "mod_btns.css"; @import "header.css"; @import "mod_tab.css"; @import "footer.css";
咱們將不一樣的部分按照必定的順序去擺放,能讓咱們的代碼看起來更加有序,易於維護,同時,有利於進行繼承或層疊覆蓋。不要小看這一步,看似無關緊要,實際要求比較高的統籌規劃能力,能夠減小冗餘代碼和快速定位問題位置等。
除此以外,咱們依然能夠有其餘的方法來幫助咱們進行區分代碼範圍,好比:
一、在文件頭部創建一個簡要的目錄
二、使用區塊註釋
在註釋中,應該儘可能詳細的寫清楚該段代碼的目的,狀態切換,調整緣由,交互邏輯等等,這樣不只利於本身的維護,更加利於別人接手維護你的代碼。
除了需求當中一些通用部分,另一些也是須要注意,但不會被正式定義的東西,它們來源於咱們的實踐經驗,好比:
層級嵌套不要太深
稍微瞭解一些瀏覽器渲染原理的都知道,它在解析CSS規則的時候,是從右向左,一層層的去遍歷尋找,若是層級太多,必然增長了渲染時間,影響渲染速度。另外,若是選擇器層級過多,也就間接反應了,你的HTML結構可能寫得不夠簡潔。
那麼具體多少層合適?通常建議是不超過4層,但話又說回來,超過4層會怎樣嗎?不會有多明顯的影響,除非你寫到很恐怖的數量,或者項目極其龐雜,可能能看出來影響,其實從咱們平常需求來看,4層之內足能夠解決絕大多數問題,故而,是合理的。
避免使用元素選擇器
出於兩點考慮:
第一點,和上一段提到的相關,在HTML中,有不少經常使用的高頻元素,好比,div、p、span、a、ul等。若是,你在多層選擇器的最內層使用了元素選擇器,那麼,在開始尋找時,瀏覽器就會遍歷HTML中的全部該元素,顯然,這是沒有必要的。
第二點,咱們的需求和代碼結構都是存在着潛在變化的,今天寫好了一個頁面,明天可能就要再加進去一個按鈕,再加進去一句話,再加進去一個圖標。咱們寫好的一個結構,也隨時可能被複用到別的結構中去。因此,若是,你使用了元素選擇器去定死某個東西,不管是新加進來的東西,仍是被複用的東西加到別的結構裏去,都極有可能產生樣式的衝突,這個時候,你又不得不寫多餘的樣式進行覆蓋修正,或者從新定義類。
因此,出於以上考慮,在具體的代碼模塊中,儘可能不要使用元素選擇器,使用元素選擇器的前提是,你徹底的肯定,不會致使出現問題。注意,我用的限定範圍是「具體的代碼模塊」,那麼用於定義通用規則的樣式,是能夠的,也是推薦使用的,好比,reset。也能夠是別的地方,這就須要咱們自行考量。
避免使用羣組選擇器
羣組選擇器會有什麼問題?直接上圖吧。
圖中這種狀況很少見,此處只是舉個例子,這裏寫了三組選擇器,用來定義不一樣地方的同一種樣式,其明顯的缺陷是,若是有第四個地方須要使用到,你不得再也不往裏加一組選擇器,若是有10個不一樣的地方,你就寫10個?這對於維護來講,是很痛苦的,聰明的咱們,怎能被如此繁複又沒必要要的勞動所困擾,故而,牆裂不推薦此種作法,徹底能夠提取出來一個公用類,定義統同樣式,而後,哪裏須要放哪裏,複用和維護都會更加方便。
固然,你可能會說,我在寫第一個的時候,不會知道後面還有那麼多,有沒有必要提取是不知道的,是的,因此,須要你根據經驗去判斷,也須要在項目推動過程當中,適時的對代碼進行整理和重構。
文件引入的數量和順序
對於剛接觸網頁的朋友來講,這兩點也是容易忽視的,由於它們看起來沒什麼大影響,多幾回請求,樣式是否已經加載,都沒那麼容易把人逼瘋。可是出於對用戶體驗的極致追求,咱們仍是但願文件請求次數儘可能少,內容的顯示有個優先順序,文件加載有個前後順序。這樣,在實在難以縮減文件大小的時候,讓用戶先看到更重要的,正常展現的內容。
以上只是幾點舉例,更多實戰結論,你們能夠多讀相關的博文或者書籍,都會有前輩們的經驗之談。
通用和語義
Naming convention is beneficial for immediately understanding which category a particular style belongs to and its role within the overall scope of the page. On large projects, it is more likely to have styles broken up across multiple files. In these cases, naming convention also makes it easier to find which file a style belongs to.
命名規則有助於當即理解一個特定樣式屬於哪一類,它在頁面的總體範圍內的做用。在大型項目中,它更可能有在多個文件中被打破的樣式。在這種狀況下,命名約定也能夠更容易地找到一個樣式屬於哪一個文件的文件。
不少時候,咱們須要一個東西被定義爲通用的,以便複用,好比:模塊標題、按鈕、提示文字、圖標等,最開始的時候,咱們習慣去看視覺稿的內容,是「新聞」,咱們就定義「news」,是「關於」,咱們就定義「about」,是紅色的按鈕,咱們就定義「red-btn」等,這樣會致使一個問題,若是有另一個跟新聞列表差很少的樣式和結構,但不是新聞,怎麼辦?繼續使用「news」顯然不合適,這就告訴咱們,不能把目光侷限於內容,須要內容和結構分離。
不能用「news」了,那用什麼呢?abc?123?這樣總不會衝突了吧,萬事大吉~其實,這是走了另外一個極端,這樣雖然在很大程度上避免了和別的模塊衝突,但其自己的可讀性就被大大下降了,別人,甚至你本身過一段時間都會忘記它是什麼,對於團隊合做是很不利的。至於須要用什麼樣的命名方式,須要你根據項目的總體來進行規劃,適合根據什麼特色來區分與之不一樣的結構,又能讓人比較容易的在名稱和結構之間創建聯繫,好比所屬類別、功能、頁面等。
團隊和我的
一個團隊當中,你們的經歷不一樣,編碼水平和習慣也不一樣,這樣就會形成,一我的一個寫法,你用中劃線,我用下劃線;我用英文全拼,你用簡寫,等等。這些雖然沒有什麼對錯之分,但對於團隊成員之間的協做形成了不小的障礙,別人必須花時間去適應和讀懂你是怎樣組織和定義的,這就無形之中提升了成本。
因此,就有了「團隊規範」存在的必要,規範除了一些寫法上的規定,讓咱們的代碼更加統1、清晰、可讀性更強、辨識度更高。還能夠提取一些最佳實踐和複用模塊等,對於團隊裏每一個人來講,都是有好處的。
固然,對於人來講,最難的,莫過於調整既有的習慣,這就會有進入一個團隊以後「轉型」的陣痛,其實這種痛也是成長的痛,你會學習到更好的編碼方式,更好的實踐方法,會從項目或者團隊的總體去考量一件事的價值和意義。
CSS和預處理器
前面我有文章詳細的談過CSS預處理器,我曾經對它也是排斥的,由於學習成本,由於以爲應用起來沒有必要。但是一旦你決定去學習使用它,就會以爲不是那樣,預處理器在向你介紹它本身的時候,就有特地強調過,它的語法是和CSS徹底兼容的,也就是說,你在LESS或者SASS文件中,直接寫CSS代碼是沒有問題的。除此以外,它能給咱們提供不少便利,好比定義統一的變量;使用嵌套而不用一直重複着寫一些選擇器;能夠提取公共的代碼塊而後很方便的複用等等。
故而,當咱們已經把CSS組織和書寫得很好了以後,預處理器,就是再次爲咱們插上一雙翅膀,能更靈活和高效的編碼。
再來簡單看看一些廣爲流傳的模式。(ps:前後順序與排名、好壞無關)
1、OOCSS——Object Oriented CSS
接觸過計算機的應該都知道,OOP——Object Oriented Programming,若是你是第一次接觸OOCSS,你會很困惑,難道是「面向對象的CSS」嗎?它不是一本真正的編程語言啊,如何面向對象?
OOCSS,最先被說起,是在2009年,它的兩大原則是:
separating structure from skin and container from content.
直譯過來就是,結構和皮膚分離,容器和內容分離。
即不要把結構和皮膚以及內容進行強耦合,而是相互獨立,所要達到的目標是更易複用和組合,能夠選擇使用,選擇引用等。
詳細瞭解連接:https://www.smashingmagazine.com/2011/12/an-introduction-to-object-oriented-css-oocss/
2、SMACSS——Scalable and Modular Architecture for CSS
從實踐上說,OOCSS給出了一種值得借鑑的思想,但在代碼的組織方面,它並未給出具體的實施方法,從這一點上來講,SMACSS更進一步。
它的核心是:
一、Base(基礎)
基礎的樣式,就是一些須要最早定義好,針對於某一類元素的通用固定樣式。
二、Layout(佈局)
佈局樣式,是跟頁面總體結構相關,譬如,列表,主內容,側邊欄的位置、寬高、佈局方式等。
三、Module(模塊)
模塊樣式,就是咱們在對頁面進行拆的過程當中,所抽取分類的模塊,這類的樣式分別寫到一塊兒。
四、State(狀態)
頁面中的某些元素會須要響應不一樣的狀態,好比,可用、不可用、已用、過時、警告等等。將這類樣式能夠組織到一塊兒。
五、Theme(主題)
主題是指版面整個的顏色、風格之類,通常網站不會有頻繁的較大的改動,給咱們印象比較深的是QQ空間,其餘應用的不是不少,因此,這個通常不會用到,但有這樣一個意識是好的,須要用到的時候,就知道該怎樣規劃。
有了以上5點分類策略,咱們的代碼組織起來,思路就會很清晰,會安排的頗有序,另外的好處是,能夠解決命名難和混亂,之因此有這個問題,主因即是咱們不知道以怎樣的標準去定義元素的所屬和特色,有了分類以後,咱們不會很隨意和混亂的去命名,有了依據,就能更輕鬆,也不易衝突。
詳細瞭解連接:https://smacss.com/
3、Meta CSS
原子類,也能夠稱之爲「無語義」類,像這樣:
它的特色是什麼?樣式和結構、內容無關,預先定義好這麼一組規則,在須要的地方加上便可,我相信每一個人第一次看到這種寫法的時候,都會想:還能這樣寫啊?!是的,總有一些人,一些新的思想和方法會涌現出來,它就是其中之一,固然,並非在稱讚其自己有多麼好,而是說這種現象和過程是好的,它自己常常被人吐槽,好比:「這樣寫和直接內聯有區別嗎?」、「若是要調整樣式,就要去改HTML,維護更加麻煩,也有違樣式和結構分離的初衷」等等,其實我我的也是不同意上面這種寫法的,若是你要把這些抽離出來,那麼還有什麼抽不出來的呢?並且這些屬性,在項目之間,頁面之間,模塊之間,並無太大的通用性,把這些抽出來,只不過是稍微懶省勁兒些,但爲了照顧到更多狀況,你必須寫入冗餘代碼,是得不償失的。
雖然它有缺點,我我的同意另外的一些東西分出來,好比:浮動(float)、文本佈局(text-align)、Flexbox佈局等,這些是沒有那麼多可能性的值,並且使用頻繁,複用方便,改動較少,除此以外,你還能夠提取另一些公共的小顆粒類,好比按鈕的種類,文字顏色的種類等,這些和CSS自己無關,和項目相關,這就是借鑑其思想,而不是直接拿來用。
4、BEM
嚴格說來,BEM不是一套有骨有肉的模式,也不只僅侷限你在CSS的層面去規劃,它是一種怎樣去組織、編寫代碼的思想,並且,看似簡單的它,對前端界的影響倒是巨大的。
它的核心以下:
Block(塊)、Element(元素)、Modifier(修飾符)
它幫助咱們定義頁面中每一部分的級別屬性,從某種意義上說,也是一種「拆」。命名規則以下:
它的出現,曾給很多人帶來啓發,可是也有另外一部分人仍然抱着挑剔的態度,譬如:
一、風格不統一,顯得代碼不夠整潔美觀
二、可能會致使類名過長
仍是前面說的,你能夠不去直接用它,但要清楚它的優勢:可以使得咱們僅經過類名就知道哪些代碼是屬於一個模塊內,以及在模塊中所起的做用。而後借鑑之。
固然,BEM集聚了不少人的心血,也獲得了不少的讚譽,其中就包括OOCSS的做者。因此,它確定不是這麼簡單。它還會告訴你,怎樣配合着js來寫,你的文件怎樣組織更好,項目該怎麼構建等。詳細能夠到官網去查閱。地址:https://en.bem.info/
到底怎樣使用設計模式?
雖然已經有成熟的設計模式,但在實際當中,你可能以爲哪一個跟本身的項目都不能徹底吻合,或者你要去爲了使用它們而調整,成本很高。其實,咱們不須要去迎合模式,要讓模式爲我所用,你須要去了解它們背後的原理,要知道它們用什麼方式解決了什麼問題,而後借鑑之,用它的方式解決咱們的問題,就好,這樣就不須要做難要不要用,也不須要糾結選哪一個,不是簡單的說哪一個好,哪一個很差,總有咱們可以用得上它的地方。海納百川,集百家衆長。
我我的一直以來所堅持的另外一個觀點就是,前端開發的三駕馬車——html、css、js,不要,也不能孤立的去談那樣好或者這樣好,咱們極少會有隻用一次的代碼或者模塊,也不會只寫一種語言,三駕馬車都是在一塊兒協做的,都是會有複用、擴展和團隊合做多方面的因素在裏面。故而,不能抱着這樣的想法:我如今就在作這個,它就是惟一的,就是固定的,沒問題。其實不少問題都是潛在的,要帶着發展眼光去看待。項目的文件之間,項目之間,團隊成員之間,不論你的分工是哪塊,都要考慮到先後的影響和可能給合做帶來的不便。
怎樣纔是最佳實踐?有「實踐」,纔有「最佳」,脫離實際狀況談最佳,就是空中樓閣。那麼,最好的模式,不是哪一個經典的模式,而是在項目進行中,不斷的磨合調整而出的。故而,不須要再害怕看起來不明覺厲的設計模式,也不須要由於本身還不懂設計模式而鬱悶,它就是人們總結出來的實戰方法,你也能夠有本身的模式~