摘要:除了其本身的語法規則,我們必須自我約束,引入語義規則,不僅僅是為了提高可讀性這樣的理由,而是拉近人與機器的距離,讓我們在思維上更加和代碼契合,這樣才能寫出優秀的程序。
前一陣子在項目組中講了一個關于CSS的Session,在講之前我曾收到了許多意見,大部分是希望能講講CSS實用性的技術,比如盒模型,CSS3之類的。干貨人人都喜歡,因為看得見摸得著,拿來就有用,但我最后還是決定講一些”濕貨“。因為在Code Diff的時候我發現了許多樣式的問題不是由于不會寫CSS導致的,而是由于在錯誤的地方使用了寫在錯誤地方的樣式。
其實CSS很簡單,沒有計算沒有流程,只是一直描述,無論什么復雜的效果,你只要Google一下就知道怎么寫了,甚至可以直接copy。但CSS又很復雜,一個元素的表現會受到它旁邊的兄弟元素,也會受到內部的子元素影響,還會受到父元素影響,在這種多重影響下,一個元素的顯示邏輯會變得錯綜復雜。有沒有面對塌陷的塊級元素而束手無策?無論怎么改它的屬性就是得不到自己想要的,但看看似乎一模一樣的示例程序卻安然無恙,是不是恨得咬牙切齒?我想這就是本文所要解決的主要問題,讓你學會如何優雅的寫CSS。
涇渭分明 - 明確書寫意圖和表現語義其實我們只要稍微接觸過CSS,一定都學過盒模型,我假設你已經對margin、padding和border已經很熟悉。好了,我們經常會遇到一種情況,想讓父元素和子元素之間有一些空間,比如布局的時候,container和content之間的留白。一般來說有兩種方式,一種是給父元素加padding內邊距,另一種是給子元素加margin外邊距。現在想想,你是否慎重考慮過用哪一種方式?你是否明白兩者的區別?如果你從未考慮過這些,現在考慮也不遲,這真的很重要,如果你真的想優雅的運用CSS,而不是被它耍的團團轉,如果你真的想把CSS寫出規模,那你就要認真的思考這里面的邏輯。
先說說父元素的container加上padding的方式,子元素的背景將不會延伸到空白區域,另一種給子元素加margin的方式則反之。但我想先拋下這個表象,看看此時加上padding的父元素的邏輯。它意味著,我創建了一個容器,并且該容器的內部有一些區域是被看不見的東西填充的,無論放入什么都不應該占據這個區域。在你的腦海中想象一個厚厚的玻璃瓶,它就好像是在說“雖然我是透明的,但是在這厚厚的玻璃之內才是你應該呆的地方,無論是什么只要你想放在瓶子里”。現在來看看子元素,是的,其背景也應該并且確實在內部,而不該占據那段空白的區域。如果是為子元素加上margin,這意味著我在容器中創建了某個東西,而這個東西有一個自己的地盤,容器內的其他東西都不能進入這里。
所以他們的本質區別在于其所表達的意義,也就是語義,一個是容器上的語義,另一個是容器內元素的語義,主語也不同,謂語意義也不同。那么這能說明什么呢,不得不提一下高級語言中的高級,這代表某個語言將機器語言封裝的更好,接口更接近自然語言,其強大不言而喻。其實編程語言的發展軌跡就是不斷把機器語言往自然語言翻譯,讓人們可以更容易的跟機器溝通,終極目標自然是人工智能,和機器用自然語言自由溝通。所以雖然代碼或者說CSS的語法并沒有什么變化,但我們應該在思維上清楚的區分代碼片段的意圖和語義來寫CSS。
語言學家喬姆斯基曾構造過一句符合語法的話:
“Colorless green ideas sleep furiously”
意思是無色的綠色想法憤怒的睡覺。想法睡覺是違反常識的,無色的綠色是矛盾的,憤怒的睡覺是不合常理的。僅僅符合語法是不夠的,僅僅不報錯也是不夠的,尤其是CSS這種描述性的語言很少會報錯,所以我想說的是,其描述性質讓我們有更多選擇來實現我們所期望的效果,但我們卻應該慎重,要讓語義分明,而不是在有限的語法規則下任意妄為,那樣寫不出好的CSS代碼。除了其本身的語法規則,我們必須自我約束,引入語義規則,不僅僅是為了提高可讀性這樣的理由,而是拉近人與機器的距離,讓我們在思維上更加和代碼契合,這樣才能寫出優秀的程序。
言歸正傳,究竟如何語義化CSS呢。之前有講過OOCSS,其實面向對象的思想就是一種語義化,將虛擬的元素看作實際的對象,用常識來構造代碼,就像是用戶體驗中的用戶習慣一樣,這是一種遍及全人類的用戶習慣,讓代碼更友好,即所謂的優雅。
比如最常見的布局,我們一般都會有header、body和footer,這樣無需任何說明和規則,誰都會理解,header在前,footer在后,中間是body。有趣的是table中的thead、tbody和tfoot,由于加載優化,我們即使把tfoot放在tbody前面,讓其先加載,但顯示的時候tfoot仍然會在tbody下面,由此可見語義化的重要,否則你一定會以為不是W3C的人弄錯了標準,就是瀏覽器廠商搞出了Bug。雖然這是HTML標簽不是CSS,但我覺得這個例子很恰當的說明了一點,顯示邏輯是獨立的,不應該和其他邏輯混為一談,它應該只關心如何顯示。
再比如,一個導航條一般分為左右兩邊,里面各有若干鏈接。你會如何命名?navbar-left和navbar-right是Bootstrap所使用的class,但當寬度減少,Responsive響應式的Bootstrap會讓這些鏈接都收進下拉菜單中,左和右又從何談起呢?同樣是Bootstrap中的顏色命名就做的十分成熟,不是green、blue、red這些詞匯,而是success、primary、warning這些詞,它們的區別是表現化與語義化的區別,我喜歡把這個叫做顯示邏輯。也就是說在class層面我們應該只關注元素(或者說對象)是用來做什么的(意圖)以及它應該表示什么(語義)。這里三種顏色代表成功、重要和警告,至于我們是用綠、藍和紅來表示還是通過其他什么顏色甚至形狀,應該在style層面寫CSS屬性表示。如此我們使用class時無需迷茫于表示成功應該用綠色還是紅色,意圖明確無誤。回到導航欄的例子,我們應該使用main和sub之類的詞語標識導航欄中重要的和次要的鏈接,即使在某些實現下,主要和次要沒有區別也不用擔心,那是該實現的顯示邏輯,我們不應該橫加干涉。
狡兔三窟 - 善用class與style多對多的復雜關系說到class和style(樣式屬性),這又是一段混亂不清的關系。其實每當我們要實現一個樣式,自覺或不自覺的都會考慮,是將元素和class一一對應,然后為元素上的class寫style,還是用class和幾條style對應之后在元素上搭配組合。前者的好處是每個class中的style不會影響其他class,但可用性十分的低,極端點說這已經不算是在編程了,而是在畫頁面;后者的好處可以靈活使用不同的樣式搭配給元素使用,組合出元素需要的效果,但很難維護,牽一發動全身,樣式很難測試,無法保證在你動了一條style之后,沒有影響其他的地方。甚至最要命的是大部分CSS代碼都是無意識的游走在這兩種情況之間,所以我們要做的不是選擇一種極端,而是找到一個平衡點,并使用一些方法使得我們的CSS既能靈活復用在各種元素上,又能易于維護,不致修了這破壞那的情況。
分組首先,對于一個或一套元素的樣式,我們應該有自己的創建原則,而不是想到哪寫到哪。比如,我一般使用這樣的步驟來創建元素:
1. 結構首先僅關注結構布局,以站點整體為基準,將元素抽象為一個或多個結構。
比如制作一個按鈕,你也許會發現它的尺寸和導航上的鏈接一致,而內外邊距以及display和overflow之類的屬性又和頁面容器一樣,這時你就可以把按鈕的結構拆成兩個結構,一個是尺寸,一個是邊界邏輯,這種情況時常發生,所以有的CSS理論認為應該把width和height這對尺寸屬性和padding以及margin這對邊距屬性徹底的分開也是這個道理。其實并不是說它們4個放一起就決定不行,只是一般它們都有各自復用的價值,所以常常被拆開使用,歸根揭底這是由顯示邏輯決定的。
2. 皮膚一般由于設計統一性,我們可以借助設計指導,輕松的制作出標準皮膚。但要注意的是,皮膚指的不僅僅甚至不一定是顏色之類的。繼續用Bootstrap舉例,有5種基礎顏色,但這并不是皮膚,5種顏色的語義不同,它們只是默認用了5種顏色,勉強可以看作默認皮膚,而真正的皮膚是theme,讓按鈕變得有立體感。還有一個誤區就是認為哪幾種屬性是皮膚,哪幾種不是。就像前面所說的,我們要在語義上進行劃分。一個屬性在某些意圖下可能是結構,在另外的意圖中可能是皮膚。
舉個極端的例子,在一個Workshop中我用CSS和HTML制作了左邊這樣的Logo,Logo本身應該完全算是皮膚,因為一般來說就是一張圖片,所以制作它的所有CSS屬性都應該算作皮膚。下面的CSS代碼中,無論是定位還是文字的處理,以及尺寸等,都是為了構造Logo,所以這些屬性都是皮膚。
css#logo i, #logo b { position: relative; } #logo i { left: -30px; transform: rotate(-30deg); font-size: 60px; letter-spacing: -11px; opacity: 0.3; } #logo b { top: -43px; left: 40px; font-size: 68px; word-break: break-all; width: 3px; line-height: 10px; text-indent: 6px; }3. 狀態
除了結構和皮膚,其實還有一類很容易被人忽視的樣式,即使是設計人員也經常忘了它,那就是狀態。最常見的是hover,鼠標觸碰元素與否的狀態,以及active,當前選中的標簽,當前所在的分頁等等。通常人們會把它劃分到皮膚中,但你要明白我們劃分的依據是意圖,很顯然,狀態不是皮膚,僅僅是通常為表達某些狀態時會使用一些顏色,畢竟顏色是最好的表示方法。它還與各種邏輯有著千絲萬縷的聯系,經常會使用JavaScript來加以控制,所以將狀態多帶帶分出來是極有必要的,JavaScript只需要更改一個class就可以實現狀態的切換,而不是在執行的時候才想起來應該把哪里隱藏把哪里顯示,或者是變個顏色出個動畫之類的。
使用接著,無論我們是已經把各種寫好的CSS屬性分好了組,還是正準備以這種方式開始寫CSS,我先引入一個語言學的術語 語塊(Lexical chunk),創造這一術語的 Michael Lewis 認為語言并非由傳統語法和詞匯組成,而是由多個詞匯的預制語塊組成。我們現在分好的組其實就是一個個CSS的語塊,CSS本身就是這種預制功能,我們要做的就是把style語塊化,然后在HTML中寫上代表它的class名稱,當HTML元素上的多個class組合在一起時就組成完整的語義。
比如表示步驟的元素,這是一個形狀類似標簽,一個挨一個的排列的元素。我將它的尺寸等屬性抽出來命名為label,然后把布局的屬性組命名為float-left,如果我的設計風格是扁平化的,我可以把相關的皮膚屬性命名為flat,你知道雖然扁平化一般用不著特別的屬性,但我也可以寫一些強制去掉圓角和漸變背景的屬性。作為步驟,會分為當前的步驟,之前的步驟,以及還沒到的步驟,當前的步驟可以命名為current,或者is—active,后面的步驟不能點所以可以命名為is-disable,這些都是狀態。而現在我們來看看當前步驟元素是什么樣的
總結成一句話就是“The flat label which float left is active”。這就是語義化的CSS。把組織好的語塊像說話一樣作用于元素上,對元素發出指令,讓其變成想要的樣式。而且你應該會發現,一組該元素所獨有的屬性,或者是尺寸之類的一般是主語,布局是動賓短語,而皮膚多是一些形容詞,最后狀態可以用表語。
總之,CSS作為一個描述性的語言,有很多人覺得不能算一種語言,但我反而覺得這是一種高級語言,因為更接近自然語言。當然其主要作用是在視覺渲染上,所以應該是一種受限的語言,可以看作是接近自然語言的子集。所以它的性質覺得了其重語義輕語法的特點,寫CSS不能僅靠語法規則,一定要用上語義規則,最好是能和項目中所有人達成共識,CSS框架其實就是一種通用共識。
原文
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/49566.html
摘要:除了其本身的語法規則,我們必須自我約束,引入語義規則,不僅僅是為了提高可讀性這樣的理由,而是拉近人與機器的距離,讓我們在思維上更加和代碼契合,這樣才能寫出優秀的程序。 前一陣子在項目組中講了一個關于CSS的Session,在講之前我曾收到了許多意見,大部分是希望能講講CSS實用性的技術,比如盒模型,CSS3之類的。干貨人人都喜歡,因為看得見摸得著,拿來就有用,但我最后還是決定講一些濕貨...
摘要:一個思維導圖是把抽象的事物具體化,以一個東西為思想核心內容,映射出一系列的組成及作用影響的內容。的思維導圖是層疊樣式表語言,是對的語言進行樣式化。我設計的思維導圖如下簡介,對象,編程語言基礎,客戶端,參考,創建與調試等等內容。 一個思維導圖是把抽象的事物具體化,以一個東西為思想核心內容,映射出一系列的組成及作用 影響的內容。 HTML的思維導圖 HTML是一種超文本標記語言。我認為要學...
摘要:一個思維導圖是把抽象的事物具體化,以一個東西為思想核心內容,映射出一系列的組成及作用影響的內容。的思維導圖是層疊樣式表語言,是對的語言進行樣式化。我設計的思維導圖如下簡介,對象,編程語言基礎,客戶端,參考,創建與調試等等內容。 一個思維導圖是把抽象的事物具體化,以一個東西為思想核心內容,映射出一系列的組成及作用 影響的內容。 HTML的思維導圖 HTML是一種超文本標記語言。我認為要學...
摘要:一個思維導圖是把抽象的事物具體化,以一個東西為思想核心內容,映射出一系列的組成及作用影響的內容。的思維導圖是層疊樣式表語言,是對的語言進行樣式化。我設計的思維導圖如下簡介,對象,編程語言基礎,客戶端,參考,創建與調試等等內容。 一個思維導圖是把抽象的事物具體化,以一個東西為思想核心內容,映射出一系列的組成及作用 影響的內容。 HTML的思維導圖 HTML是一種超文本標記語言。我認為要學...
閱讀 617·2023-04-25 18:37
閱讀 2780·2021-10-12 10:12
閱讀 8315·2021-09-22 15:07
閱讀 564·2019-08-30 15:55
閱讀 3174·2019-08-30 15:44
閱讀 2194·2019-08-30 15:44
閱讀 1625·2019-08-30 13:03
閱讀 1560·2019-08-30 12:55