像「class="btn btn-large btn-block btn-primary"」這樣的 CSS 使用風格好嗎?

雖然說這樣可以解藕,提高代碼復用,但是我經常在代碼里看到大樣相同的 class 列表。我認為這直接違背了 DRY 原則,而且從某種角度來看,跟用 Word 上格式刷、使用 style 屬性沒有區別。

所以:

一、現在很多人使用這種寫法,好嗎?

二、好的話,對比我下面提的兩種解法,有何優勢?

三、不好的話,在 CSS 層面 mixin 是個好的解法嗎?

四、或者:

&

或者其它方式,然後對 HTML 中使用 big-large-huge-button 的元素的 class list 做個轉換,這樣好嗎?


如果不藉助CSS預處理器來說,還是有其一定的優勢。拿個簡單的示例來說吧:

這兩個Button長得非常的相似,就背景顏色不一樣,如果只使用一個類:

&Twitter&
&Facebook&

樣式自然也就跟著來了:

/*twitter button*/
.twitterbtn {
border:3px solid #000;
padding:10px 20px;
color:#fff;
border-radius:10px;
background:red;
}
/*facebook button*/
.facebookbtn {
border:3px solid #000;
padding:10px 20px;
color:#fff;
border-radius:10px;
background:blue;
}

很容易會發現,上面的樣式有很多重複的代碼。在CSS中,可以將這個樣式稱之為公用樣式,或許你首先想到的是,將兩個按鈕公用樣式提取出來,通過組合選擇器來處理。

.twitterbtn,
.facebookbtn{
border:3px solid #000;
padding:10px 20px;
color:#fff;
border-radius:10px;
}
.twitterbtn{
background:red;
}
.facebookbtn{
background:blue;
}

少的時候你這樣使用也無防,但如果使用的地方多起來了呢?比如我還有別的按鈕之類。這種方法是不是又有其欠缺之處。也有同學就會想到使用你提出來的多類問題了:

&Twitter&
&Facebook&

.btnbase {
border:3px solid #000;
padding:10px 20px;
color:#fff;
border-radius:10px;
}
.twitter {
background:red;
}
.facebook {
background:blue;
}

相互比較一下,就清楚哪種更適合。仁者見仁,智者見智。哪個更好,更適合,還是自己考慮。至於說維護不好,造成覆蓋,個人覺得還是要思考一下自己的組織代碼方式之類的。

基於這個上面,如果能結合Sass或LESS這樣的CSS預處理器,就會更輕鬆了。拿Sass來說吧,你完全可以把.btnbase的樣式聲明成一個混合宏或一個placeholder(我更人更趨向於placeholder),如:

//SCSS
%btnbase {
border:3px solid #000;
padding:10px 20px;
color:#fff;
border-radius:10px;
}
.twitterbtn {
@extend %btnbase;
background:red;
}
.facebookbtn {
@extend %btnbase;
background:blue;
}

//編譯出來的CSS
.twitterbtn, .facebookbtn {
border: 3px solid #000;
padding: 10px 20px;
color: #fff;
border-radius: 10px;
}

.twitterbtn {
background: red;
}

.facebookbtn {
background: blue;
}

草畫了一個對比圖,不一定完全正確,僅供參考:

相關方面的,建議去閱讀有關於OOCSS和OOSass相關的,自己去對比,尋找,是否適合與不適合。別人的東西也不一定是適合你的。


簡單說,不好。

這個問題我回答很多次了,可搜我的相關問答。也可以看這篇:如何看待《React: CSS in JS》? · Issue #22 · hax/hax.github.com · GitHub 。我雖然不贊同facebook的解決方案,但是這篇slide前半部分說明了這種方法在工程上的問題。


認知問題不能只從一個角度出發,詳解下:

1. 這種風格主要是用於css框架,框架提供諸多功能樣式,開發者調用相應的class即可表現出來。

2. 不推薦自己開發的時候使用這種模式,也沒必要,反而表意不清楚。

3. 還有更誇張的,例如font-12,font-14,font-16,align-left,color-red,color-green。這種的場景是什麼?

最近我在寫一個管理系統,裡面的組件基本都長得差不多,但是還是經常有定製性的小樣式更改。

我使用了一個css框架後基本不用自己寫樣式了,但是一些細節樣式還是需要微調,我要為這些樣式單獨建一個css文件么?我們的css開發都是less模塊化的,如果我要給這個微調建立css,那我就需要建立N個裡面只寫幾句css的less模塊。真是蛋疼。

於是我們就把常用樣式都抽取成了原子化的class名,大的框架使用通用的樣式,小的修改使用atom.css里提供的原子化的class來組合,從此再也不怕小的樣式修改了。

目前我們做的主要是字體,顏色,背景,padding,margin,align,vertical-align之類的抽取。

每個東西都有自己存在的意義,不過還是希望大牛們把這些東西能講清楚,不要單純的給大家散播一些觀點,然後導致大家片面的理解和濫用。

該用什麼的地方就用什麼,用一個東西之前想好為什麼要這麼用即可。


1,有好的地方,有不好的地方。

2,沒有看懂你下面提供的其他方式的意思,這種方式是需要 CSS3 的 [data-class-list=*] 選擇器嗎?還是說要藉助 JS 來處理?

3,還是需要應對不同的場景來判斷是否要使用掛類或者直接在代碼裡面 mixin。

下面來具體說下我個人的想法,如果有缺陷或不足,歡迎指點。

沒有什麼方案是完全對的或者完全錯的,也不應該根據使用人數多少來判斷,每種規劃都有自己適應的場景。

這種類名的規劃方式主要目的是共用 CSS 代碼。常見元素例如 btn 或者 icon,btn 按鈕可能顏色不同,但具有相同的 size 或者 font 屬性;所有的 icon 圖標可能都有一樣的 size 只是 bg-image 不一樣。而且這些元素不會在頁面中大量使用(因此不會需要頻繁修改 HTML),也具有足夠高的獨立性,那麼我們就可以使用這種類名規劃方式。但是你這個例子中的規劃還是不合適的,後面會說。

舉一個應該在代碼裡面 mixin 的例子,clearfix 類。clearfix 類是用來清除浮動的類,只需要將其放在需要清除浮動的 HTML 結構中即可。但是它需要大量使用,這樣就可能需要你來回切換 HTML 和 CSS 來將該類放在某個結構或者從某個結構中去掉。而且這樣的用法類似 w100(width 100px)原子類以及被拋棄的 font 標籤那樣,將樣式跟 HTML 偶合在一起了。如果你想要去掉它的浮動,雖然清除浮動是靠 CSS 來實現,但你還是需要去修改 HTML。所以這種類就可以 mixin 到代碼裡面,用 SASS 的花,直接 @extend .clearfix; 即可。

所以怎麼用,還是需要看需求,考慮維護方便。上面提到了命名不好,主要考慮到維護性。Bootstrap 裡面出現這種代碼情有可原,它的目的是儘可能的提供各種場景的 CSS,盡最大限度的讓你少寫 CSS,但維護起來就比較菊緊,你有點改動只能靠覆蓋,而不太方便去修改 Bootstrap 的源代碼。

如果你自己定義的話,建議只保留兩個類,即:btn btn-primary。分成兩個類,已經足夠細分,此外維護也方便。btn 定義按鈕通用的,btn-primary 定義某個特定按鈕的具體樣式,如果遇到了同類按鈕不同的樣式(例如相同顏色,不同大小),可以使用父類作進一步定義 .item-wrap .btn{ *** } 或者 .item-wrap .btn-primary (根據是所有按鈕都變還是特定按鈕)。

此外類名命名也有講究,要以功能命名(primary、error、login、submit),而不是屬性(red、green、large),如果一個出錯的按鈕 error,你使用 btn btn-red 來定義,後面假設需求方的 VI 系統吧 error 這類警示顏色換成了黃色,那麼你不得不新增 btn-yellow 並修改 HTML 中類名 btn btn-yellow 或者直接在 CSS 將 btn-red 的 bgcolor 修改成 yellow,後者雖然方便,但後面維護者就疑惑了,明明是 btn-red 你為啥顯示個黃顏色?


這種用法的好與不好在於權衡。在沒有應用場景的情況下單純的討論好與不好是沒太多意義的。

首先明確的說一下,這種用法是可取的,但是不能濫用。

class的定義 可以是針對一個模塊(標籤),描述它所有應該擁有的屬性。

但是 當一個模塊擁有的屬性太多,並且我們希望幾個相關聯的屬性是可以實現復用的時候我們會把他抽出來單獨成一個新的class。

所以關鍵問題就在於怎麼抽離可復用的屬性。這個抽離的粒度太細就變得沒意義。恰當合適就變得有意義了。

當然現在的css語法糖,可以實現在css裡面引用,完全避免一個標籤多個class的情況,唯一的弊端就是css文件會變得臃腫。

所以這些事情沒有絕對的利於弊,好與壞。純粹就是看你怎麼對自己項目做一個權衡。


大部分時候不好。混亂而難以管理,過多使用這種方式等於放棄了 dom 樹的層次性,以後維護的過程中要局部改樣式就難辦了。

為什麼還用?

一種情況是使用了現成的前端框架,框架內部添加了一大堆這樣的 class。框架使用這種方式有他們的道理,因為這樣比較容易換膚,並且框架也不知道你的 dom 結構,沒有辦法利用,使用這種方式能做到全自動。

另一種是類似 hidden 這種 class,用多了肯定不好,但是適當的出現有助於在 js 中方便地切換顯示狀態。尤其是單頁應用,切來切去的情況太多,如果你不是用 url 路由方式,使用這樣的 class 會比較簡單。


角度不同而已,何談好與不好,自己用著順手,並且能解決問題,就不能算是不好


這種寫法必須有強力的「約定做支撐」,員工培訓等都必須做好,而且最好有詳細的文檔,如果能到以上幾點,這麼寫是個不錯的方案,因為便於分類和理解。

當然現實中可沒有這麼規範,拿來利用,大家自顧自寫的情況很多,所以這個方案是有問題的。

但是你嘗試著去想這個問題,你會越來越沮喪,因為css本身是全局的,想想看所有的變數都是全局的情況下也只能做到如此。

雖然寫行內樣式的能解決全局污染的問題,但是管理起來又是一個麻煩,而且不支持很多方便的css功能,所以最後你所能做的也只能這樣然後通過各種規範來防止全局的問題。

所以,這個方案的確不夠完美,但是現階段這或許是比較好的方案


最好的應該是

class="btn large block primary"

但是這樣性能不高,兼容性不強(可惡的 IE6)


這是一個編程問題。可以轉化為寫流水代碼(過程代碼),和面向對象代碼的優缺點。流水代碼在某些情況不一定是壞事,假如只用一次,為什麼要抽離呢,還非地搞個prototype呢。與此同時,每個面向對象function裡面也蘊含很多過程性代碼,就是代碼耦合度。過度耦合和解耦都是不利於項目發展的。

------

合適就好。


這就是目前最標準的風格,我比較推薦網易的命名風格,Facebook遇到的問題99%的網站都遇不到。


這種寫法是框架針對不能得心應手操作CSS的人員設計的,你能玩好CSS,就自己組織一套,來替換框架提供的方案就行了。


我是分情況來用的:

在做UI組件的時候,這樣做復用和靈活比較大!

但是在單獨功能模塊下面,這樣做無非是作死……


我想說我在我團隊根本就實踐不了Sass的extend,他們都視這玩意兒為累贅,我寫出來了他們也維護不了,舞台太小,蛋疼


推薦閱讀:

前端開發中如何做到頁面安全,防止 xss ,csrf 這樣的欺騙及偽造?
hexo怎麼添加留言板?
純前端如何抵禦CSRF攻擊?
你在什麼情況下會選擇使用 Backbone.js 或 AngularJS?
shadow dom可以做什麼用?

TAG:前端開發 | CSS | 編程 | 頁面重構 |