首頁  >  文章  >  web前端  >  談CSS的設計模式

談CSS的設計模式

高洛峰
高洛峰原創
2017-02-09 17:05:581177瀏覽

什麼是設計模式?

  曾有人調侃,設計模式是工程師用來跟別人顯擺的,顯得高大上;也曾有人這麼說,不是設計模式沒用,是你還沒到能懂它,會用它的時候。

  先來看一下比較官方的解釋:「設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類的、程式碼設計經驗的總結。使用設計模式是為了可重用程式碼、讓程式碼更容易被他人理解、保證程式碼可靠性。的結構一樣。

  設計模式,這個詞彙我們常見,幾乎所有的程式語言都會有幾套,但深入研究的人不多,原因如下:

  1、似乎沒有太大必要性去強調它,有問題了改一下或者按團隊規範來就行;

  2、不去使用一些既有的模式也無傷大雅;

  3、不少人所接觸的業務量級還沒有達到需要規劃和組織的程度,光寫佈局,寫特效,照顧兼容,就夠喝一壺的了,沒有意識去思考一些方法論的問題。

  當然,這三者都是我經歷過的,相信你也是~

  我們都會長大,都會慢慢的做更多、更大、更複雜的項目,這個時候,就需要自上而下,全流程的去思考一些問題。後台不說,只講前端,例如:風格的製定、色調、模組、佈局方式、互動方式、邏輯等等,如果再加上團隊合作,若再沒有一個規劃的話,要不了多久,那些看起來沒問題的程式碼,就會暴露出各種問題,模組命名、類別的命名、檔案的組織、共用模組的擷取、程式碼的複用、可讀性、擴充性、維護性。它們看起來只是一些簡單的小動作,卻需要你看得更遠,避免將來出問題需要付出更大的代價,甚至被迫整個項目重構,可謂,功在當代,利在千秋~

  既然要對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";

  我們將不同的部分按照一定的順序去擺放,能讓我們的代碼看起來更加有序,易於維護,同時,有利於進行繼承或層疊覆蓋。不要小看這一步,看似可有可無,實際要求比較高的統籌規劃能力,可以減少冗餘程式碼和快速定位問題位置等。

  除此之外,我們依然可以有其他的方法來幫助我們進行區分程式碼範圍,例如:

  1、在文件頭部建立一個簡要的目錄

谈CSS的设计模式

  2、使用區塊註釋

谈CSS的设计模式

  在註釋中,應該盡量詳細的寫目的,該程式碼交互邏輯等等,這樣不僅利於自己的維護,更有利於別人接手維護你的程式碼。

  從結論出發

  除了需求當中一些通用部分,另外一些也是需要注意,但不會被正式定義的東西,它們來自我們的實踐經驗,例如:

  層級嵌套一個稍微深厚。了解一些瀏覽器渲染原理的都知道,它在解析CSS規則的時候,是從右向左,一層層的去遍歷尋找,如果層級太多,必然增加了渲染時間,影響渲染速度。另外,如果選擇器層級過多,也就間接反應了,你的HTML結構可能寫得不夠簡潔。

  那麼具體多少層合適?一般建議是不超過4層,但話說回來,超過4層會怎麼樣嗎?不會有多明顯的影響,除非你寫到很恐怖的數量,或者項目極其龐雜,可能能看出來影響,其實從我們日常需求來看,4層以內足可以解決絕大多數問題,故而,是合理的。

  出於兩點考慮:

  第一點,和上一段提到的相關,在HTML中,有很多常用的高頻元素,例如,p、p、span、a 、ul等。如果,你在多層選擇器的最內層使用了元素選擇器,那麼,在開始尋找時,瀏覽器就會遍歷HTML中的所有該元素,顯然,這是不必要的。

  第二點,我們的需求和程式碼結構都是存在著潛在變化的,今天寫好了一個頁面,明天可能就要再加進去一個按鈕,再加進去一句話,再加進去一個圖示。我們寫好的一個結構,也隨時可能被重複使用到別的結構中去。所以,如果,你使用了元素選擇器去定死某個東西,不論是新加進來的東西,還是被復用的東西加到別的結構裡去,都極有可能產生樣式的衝突,這個時候,你又得寫多餘的樣式進行覆蓋修正,或是重新定義類別。

  所以,出於以上考慮,在具體的程式碼模組中,盡量不要使用元素選擇器,使用元素選擇器的前提是,你完全的確定,不會導致出現問題。注意,我使用的限定範圍是“具體的程式碼模組”,那麼用於定義通用規則的樣式,是可以的,也是建議使用的,例如,reset。也可以是別的地方,這就需要我們自行考慮。

  避免使用群組選擇器

  群組選擇器會有什麼問題?直接上圖吧。

  圖中這種情況不多見,此處只是舉個例子,這裡寫了三組選擇器,用來定義不同地方的同一種樣式,其明顯的缺陷是,如果有第四個地方要用到,你必須再往裡加一組選擇器,如果有10個不同的地方,你就寫10個?這對於維護來說,是很痛苦的,聰明的我們,怎能被如此繁復又不必要的勞動所困擾,故而,牆裂不推薦此種做法,完全可以提取出來一個公用類,定義統一樣式,然後,哪裡需要放哪裡,復用和維護都會更方便。

  當然,你可能會說,我在寫第一個的時候,不會知道後面還有那麼多,有沒有必要提取是不知道的,是的,所以,需要你根據經驗去判斷,也需要在專案推進過程中,適時的對程式碼進行整理與重構。 谈CSS的设计模式

  文件引入的數量和順序

  對於剛接觸網頁的朋友來說,這兩點也是容易忽視的,因為它們看起來沒什麼大影響,多幾次請求,樣式是否已經加載,都沒那麼容易把人逼瘋。但出於對使用者體驗的極致追求,我們還是希望文件請求次數盡量少,內容的顯示有個優先順序,文件載入有個先後順序。這樣,在實在難以縮減文件大小的時候,讓使用者先看到更重要的,正常展示的內容。

  以上只是幾點舉例,更多實戰結論,大家可以多讀相關的博文或書籍,都會有前輩們的經驗之談。

  從矛盾出發

  通用和語義

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 morelike like the mampkk mooc​​king the memem​​ion sgoly have the memunike the mem. also makes it easier to find which file a style belongs to.

  命名規則有助於立即理解一個特定樣式屬於哪一類,它在頁面的整體範圍內的作用。在大型專案中,它更可能有在多個文件中被打破的樣式。在這種情況下,命名約定也可以更容易找到一個樣式屬於哪個檔案的檔案。

  很多時候,我們需要一個東西被定義為通用的,以便復用,比如:模組標題、按鈕、提示文字、圖標等,最開始的時候,我們習慣去看視覺稿的內容,是“新聞” ,我們定義“news”,是“關於”,我們定義“about”,是紅色的按鈕,我們就定義“red-btn”等,這樣會導致一個問題,如果有另外一個跟新聞列表差不多的樣式和結構,但不是新聞,怎麼辦?繼續使用「news」顯然不合適,這就告訴我們,不能把目光侷限於內容,需要內容和結構分開。

  不能用「news」了,那用什麼呢? abc? 123?這樣總不會衝突了吧,萬事大吉~其實,這是走了另一個極端,這樣雖然在很大程度上避免了和別的模組衝突,但其本身的可讀性就被大大降低了,別人,甚至你自己過一段時間都會忘記它是什麼,對團隊合作來說是很不利的。至於需要用什麼樣的命名方式,需要你根據專案的整體來進行規劃,適合根據什麼特點來區分與之不同的結構,又能讓人比較容易的在名稱和結構之間建立聯繫,例如所屬類別、功能、頁面等。

  團隊和個人

  一個團隊當中,大家的經歷不同,編碼水平和習慣也不同,這樣就會造成,一個人一個寫法,你用中劃線,我用下劃線;我用英文全拼線,你用英文全拼線,你用簡寫,等等。這些雖然沒有什麼對錯之分,但對於團隊成員之間的協作造成了不小的障礙,別人必須花時間去適應和讀懂你是怎樣組織和定義的,這就無形之中提高了成本。

  所以,就有了「團隊規範」存在的必要,規範除了一些寫法上的規定,讓我們的代碼更加統一、清晰、可讀性更強、辨識度更高。還可以提取一些最佳實踐和復用模組等,對於團隊裡每個人來說,都是有好處的。

  當然,對於人來說,最難的,莫過於調整既有的習慣,這就會有進入一個團隊之後「轉型」的陣痛,其實這種痛也是成長的痛,你會學習到更好的編碼方式,更好的實踐方法,會從專案或團隊的整體去考慮一件事的價值和意義。

  CSS和預處理器

  前面我有文章詳細的談過CSS預處理器,我曾經對它也是排斥的,因為學習成本,因為覺得應用起來沒有必要。可是一旦你決定去學習使用它,就會覺得不是那樣,預處理器在向你介紹它自己的時候,就有特意強調過,它的語法是和CSS完全相容的,也就是說,你在LESS或者在SASS檔案中,直接寫CSS程式碼是沒有問題的。除此之外,它能給我們很多便利,例如定義統一的變數;使用嵌套而不用一直重複著寫一些選擇器;可以提取公共的程式碼區塊然後很方便的複用等等。

  故而,當我們已經把CSS組織和書寫得很好了之後,預處理器,就是再次為我們插上一雙翅膀,能更靈活和高效的編碼。

  從現有模式出發

  再來簡單看看一些廣為流傳的模式。 (ps:先後順序與排名、好壞無關)

  一、OOCSS——Object Oriented CSS

  接觸過計算機的應該都知道,OOP——Object Oriented Programming,如果你是第一次接觸OOCSS,你會很困惑,難道是「物件導向的CSS」嗎?它不是一本真正的程式語言啊,如何面向對象?

  OOCSS,最早被提及,是在2009年,它的兩大原則是:

  separating structure from skin and container from content.

  直譯容器,結構和內容分離。

  即不要把結構和皮膚以及內容進行強耦合,而是相互獨立,所要達到的目標是更易復用和組合,可以選擇使用,選擇引用等。

  二、SMACSS——Scalable and Modular Architecture for CSS

  從實踐上說,OOCSS給出了一種值得借鑒的思想,但在代碼的組織方面,它並未給出具體的實施方法,從這一點上來說,SMACSS更進一步。

  它的核心是:

  1、Base(基礎)

  基礎的樣式,就是一些需要最先定義好,針對於某一類元素的通用固定樣式。

  2、Layout(佈局)

  佈局樣式,是跟頁面整體結構相關,譬如,列表,主內容,側邊欄的位置、寬高、佈局方式等。

  3、Module(模組)

  模組樣式,就是我們在對頁面進行拆的過程中,所抽取分類的模組,這類的樣式分別寫在一起。

  4、State(狀態)

  頁中的某些元素會需要回應不同的狀態,例如,可用、不可用、已使用、過期、警告等等。將這類樣式可以組織在一起。

  5、Theme(主題)

  主題是指版面整個的顏色、風格之類,一般網站不會有頻繁的較大的改動,給我們印像比較深的是QQ空間,其他應用的不是很多,所以,這個一般不會用到,但有這樣一個意識是好的,需要用到的時候,就知道該怎麼規劃。

  有了以上5點分類策略,我們的程式碼組織起來,思路就會很清晰,會安排的很有序,另外的好處是,可以解決命名難和混亂,之所以有這個問題,主因便是我們不知道以怎樣的標準去定義元素的所屬和特點,有了分類之後,我們不會很隨意和混亂的去命名,有了依據,就能更輕鬆,也不易衝突。

  三、Meta CSS

  原子類,也可以稱之為「無語意」類,像這樣:

谈CSS的设计模式

  它的特徵是什麼?樣式和結構、內容無關,預先定義好這麼一組規則,在需要的地方加上即可,我相信每個人第一次看到這種寫法的時候,都會想:還能這樣寫啊? !是的,總有一些人,一些新的思想和方法會湧現出來,它就是其中之一,當然,並不是在稱讚其本身有多麼好,而是說這種現象和過程是好的,它本身常被人吐槽,例如:「這樣寫和直接內聯有區別嗎?」、「如果要調整樣式,就要去改HTML,維護更加麻煩,也有違樣式和結構分離的初衷」等等,其實我個人也是不贊成上面這種寫法的,如果你要把這些抽離出來,那還有什麼抽不出來的呢?而且這些屬性,在專案之間,頁面之間,模組之間,並沒有太大的通用性,把這些抽出來,只不過是稍微懶省勁兒些,但為了照顧到更多情況,你必須寫入冗餘程式碼,是得不償失的。

  雖然它有缺點,我個人贊成另外的一些東西分出來,比如:浮動(float)、文字佈局(text-align)、Flexbox佈局等,這些是沒有那麼多可能性的值,而且使用頻繁,復用方便,改動較少,除此之外,你還可以提取另外一些公共的小顆粒類,比如按鈕的種類,文字顏色的種類等,這些和CSS本身無關,和項目相關,這就是藉鑑其思想,而不是直接拿來用。

  四、BEM

  嚴格說來,BEM不是一套有骨有肉的模式,也不僅僅局限你在CSS的層面去規劃,它是一種怎樣去組織、編寫程式碼的思想,而且,看似簡單的它,對前端界的影響卻是巨大的。

  它的核心如下:

  Block(塊)、Element(元素)、Modifier(修飾符)

  它幫助我們定義頁面中每一部分的級別屬性,從某種意義上說,也是一種「拆說,也是一種「拆說」。命名規則如下:

谈CSS的设计模式

  它的出現,曾給不少人帶來啟發,但是也有另一部分人仍然抱著挑剔的態度,譬如:

  1、風格不統一,顯得代碼不夠美觀

  2、可能會導致類別名稱過長

  還是前面說的,你可以不去直接用它,但要清楚它的優點:能夠使得我們僅透過類別名稱就知道哪些程式碼是屬於一個模組內,以及在模組中所起的作用。然後借鏡之。

  當然,BEM集聚了很多人的心血,也得到了很多的讚譽,其中就包括OOCSS的作者。所以,它肯定不是這麼簡單。它還會告訴你,怎樣配合著js來寫,你的檔案怎樣組織更好,專案該怎麼建置等。詳細可以到官網查閱。

  從實際出發,決定結果的人是你

  到底怎樣使用設計模式?

  雖然已經有成熟的設計模式,但在實際當中,你可能覺得哪個跟自己的專案都不能完全吻合,或者你要去為了使用它們而調整,成本很高。其實,我們不需要去迎合模式,要讓模式為我所用,你需要去了解它們背後的原理,要知道它們用什麼方式解決了什麼問題,然後藉鑑之,用它的方式解決我們的問題,就好,這樣就不需要作難要不要用,也不需要糾結選哪個,不是簡單的說哪個好,哪個不好,總有我們能夠用得上它的地方。海納百川,集百家眾長。

  我個人一直以來所堅持的另一個觀點就是,前端開發的三駕馬車——html、css、js,不要,也不能孤立的去談那樣好或者這樣好,我們極少會有隻用一次的程式碼或模組,也不會只寫一種語言,三駕馬車都是在一起協作的,都是會有復用、擴展和團隊合作多方面的因素在裡面。故而,我不能抱著這樣的想法:我現在就在做這個,它就是唯一的,就是固定的,沒問題。其實很多問題都是潛在的,要帶著發展眼光去看。在專案的文件之間,專案之間,團隊成員之間,不論你的分工是哪塊,都要考慮到前後的影響和可能給合作帶來的不便。

  怎樣才是最佳實踐?有“實踐”,才有“最佳”,脫離實際情況談最佳,就是空中樓閣。那麼,最好的模式,不是哪個經典的模式,而是在專案進行中,不斷的磨合調整而出的。故而,不需要再懼怕看起來不明覺厲的設計模式,也不需要因為自己還不懂設計模式而鬱悶,它就是人們總結出來的實戰方法,你也可以有自己的模式~

更多談CSS的設計模式 相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn