基于CSS color屬性的靜態UI組件重構策略
一、傳統靜態UI組件實現的隱隱痛點
我們都知道,一個網站,只要設計師稍微有點專業,其站點的一些基礎顏色都是貫穿始終的。
主色,鏈接色,警示顏色,以及各種狀態顏色等等,都是一脈相承的,如果貴站的文字的紅色和按鈕的紅色是不一樣的紅色,文字的綠色和按鈕的綠色不是一個綠色,文字的藍色和按鈕的藍色不是一個藍色,我只能深表遺憾。
傳統的實現,包括現在移動端幾乎所有的實現套路都是下面這樣的,無論是標簽還是按鈕,都是先設定一個基礎類名,寫下基本樣式,然后不同的顏色重新命名一個狀態類名,覆蓋默認的邊框色或者背景色或者文字顏色,是什么顏色就寫什么顏色。
我們不妨看看微信開源的weui中按鈕的實現: https://weui.io/#button
HTML部分:
<a href="#" class="weui_btn weui_btn_primary">按鈕</a>
<a href="#" class="weui_btn weui_btn_warn">確認</a>
<a href="#" class="weui_btn weui_btn_default">按鈕</a>
對應的CSS實現如下:
.weui-btn {
position: relative;
display: block;
margin-left: auto; margin-right: auto;
padding-left: 14px; padding-right: 14px;
box-sizing: border-box;
font-size: 18px;
text-align: center;
text-decoration: none;
color: #FFFFFF;
line-height: 2.55555556;
border-radius: 5px;
overflow: hidden;
}
.weui-btn_primary {
background-color: #1aad19;
}
.weui-btn_default {
color: #000000;
background-color: #F8F8F8;
}
.weui-btn_warn {
background-color: #E64340;
}
/* 下面是2個線框按鈕 */
.weui-btn_plain-default {
color: #353535;
border: 1px solid #353535;
}
.weui-btn_plain-primary {
color: #1aad19;
border: 1px solid #1aad19;
}
基本上,我們都是這么實現的,用起來也還行,但是,不知道大家在寫類似上面代碼的時候,有沒有一種冗余和啰嗦的感覺?——就顏色不一樣而已,但是,卻要重新命名一個類名,然后重新寫顏色;只要再多一個狀態,就要再寫一批。好麻煩!
為什么隱隱會有上面這樣的感覺呢?
我來帶大家剖析下。
1. 按鈕狀態
本質上,按鈕就3個狀態,常用態,默認態和警示態,但是,從類名的數量上來看,卻要5個,而且命名上又長有啰嗦,真的很難忍受,如果再和weui中按鈕禁用樣式混在一起,足有這么長,看我的手臂,全部張開都不夠啊!例如下面這個綠色小按鈕的禁用態表示:
<a href="#" class="weui-btn weui-btn_mini weui-btn_primary weui-btn_disabled">按鈕</a>
實際上,我們可以把狀態單獨抽象出來,如: default , primary , warn , mini , disabled ,與基礎按鈕樣式相互結合,生成UI效果,這樣,在HTML中使用類名的時候會清爽很多,而且記憶的成本也降低了。
如果上面的按鈕套用這種策略,則代碼應該類似下面:
HTML部分:
<a href="#" class="weui_btn primary">按鈕</a>
<a href="#" class="weui_btn warn">確認</a>
<a href="#" class="weui_btn default">按鈕</a>
對應的CSS實現如下:
.weui-btn {
...
}
.weui-btn.primary {
background-color: #1aad19;
}
.weui-btn.default {
color: #000000;
background-color: #F8F8F8;
}
.weui-btn.warn {
background-color: #E64340;
}
/* 下面是2個線框按鈕 */
.weui-btn_plain.default {
color: #353535;
border: 1px solid #353535;
}
.weui-btn_plain.primary {
color: #1aad19;
border: 1px solid #1aad19;
}
當然,對于weui這種開源的項目而言,上面基于狀態類名策略不一定合適,因為和其他項目混雜,容易有沖突風險。
2. 各種顏色
例如 primary 狀態,明明色值都是一模一樣的 #1aad19 ,但是上下卻出現了3次,如果使用Sass, Less變量還好,要是傳統的CSS寫法,以后換起顏色來,怕是要一個一個替換了。
每一種狀態都要寫一批顏色,要是遇到狀態多的場景(如下面這張項目設計稿截圖 – 先用demo截圖代替,明早更新):
臥槽,那樣式就要茫茫多了,一行行全部邊框色文字顏色,邊框色文字顏色,不過凡事都要兩面看,至少這樣子代碼看上去很壯觀。
每一種顏色狀態都要寫一遍 color 屬性和 border 屬性,這種做苦力的感覺沒人會喜歡的,明明是重復的東西,難道就不能前端工程化嗎?
實際上,以上兩個隱隱的痛點可以一次性全部搞定,就是采用本文所要介紹的“ 基于color屬性的UI組件重構策略 ”。
二、CSS color屬性驅動的靜態UI組件實現策略
這種實現策略具體如下:
- 提取專門的顏色類名
例如,類似下面這樣:
.dark { color: #33373d; } .gray { color: #969ba3; } .blue { color: #4284ed; } .green { color: #7ed321; } .orange { color: #f0643a; } .yellow { color: #f0c53a; } .purple { color: #a091ff; } .red { color: #ed424b; } .white { color: #fff; }
然后,建議放在所有公用樣式的最底部。
- 靜態UI組件所有動態顏色全部走原生變量
例如, border 邊框色默認就是 color 屬性的顏色,因此,寫 border 時候,顏色值可以直接缺省,直接:.btn-normal { border: 1px solid; }
對于背景色,我們可以走CSS的 currentColor 變量。
.btn-normal { background-color: currentColor; }
- 顏色類名既扮演狀態類名角色又扮演顏色控制角色
HTML直接變成類似下面這樣:<a href="" class="btn-normal red">紅色按鈕</a> <a href="" class="btn-normal blue">藍色按鈕</a> <a href="" class="btn-normal green">綠色按鈕</a>
- 大功告成!
我們看一個具體例子加深理解,關于實色按鈕的實現。同樣的,我們有一個基礎的類名和基本樣式:
.btn-normal {
font-size: 14px;
line-height: 30px;
display: inline-block;
padding: 0 16px;
text-align: center;
border-radius: 2px;
background-color: currentColor;
}
注意,和傳統實現不一樣,我們這里直接指定了背景色,但是是以 currentColor 變量的形式,也就是背景色和我們的文字顏色保持一致。
什么?背景色和我們的文字顏色!那豈不是按鈕文字顏色和背景色混在一起,看個毛啊!
沒錯,按鈕的文字顏色確實不能和背景色一樣,但是,由于通常按鈕上的文字都只有一行,于是,注意,本文最精華部分來了——考慮到按鈕上的文字都是白色,因此我們可以這樣處理:
.btn-normal::first-line {
color: #fff;
}
利用 ::first-line 偽元素,于是, .btn-normal 標簽上的顏色實際上是設置給 background-color 的,而真正按鈕呈現的顏色已經被 ::first-line 偽元素牢牢設置好了,完全就不用擔心文字顏色和背景色混在一起的情況了。
于是乎,配合基礎顏色類名,各種顏色按鈕全部都出來了。
要實現設計師設計的綠色和紅色按鈕,直接HTML:
<a href="#" class="btn-normal green">綠色按鈕</a>
<a href="#" class="btn-normal red">紅色按鈕</a>
后來,設計師突然發現這兩者顏色按鈕不夠用,又設計了一款同尺寸的藍色按鈕,如果是傳統實現,那必須要分別給實色按鈕和線框按鈕重新起個命名,而且要在CSS代碼中繼續添加相關的背景色和邊框色樣式代碼,你說煩不煩啊!如果是基于 color 屬性實現,我去,工作量不要太輕松,直接HTML加個 blue 類名就可以了:
<a href="#" class="btn-normal blue">藍色按鈕</a>
沒錯,結束了,CSS文件都不需要打開了,實際上,一個基礎按鈕樣式寫好,其實等同于所有顏色的按鈕全部都寫好了。
這孰優孰劣明眼人一看就看得出來了。
而且,最最關鍵的是,這稍微有點分量的項目中的靜態UI組件可不止按鈕這一種啊!
各種顏色文字本質也是UI組件,然后,各種等級標簽,榮譽標簽,特殊按鈕,還有模擬控件啊,等等。
如果所有的這些靜態UI組件全部都采用基于 color 屬性實現的策略,那這些顏色就成為了真正意義上的貫穿整個項目的顏色變量了,這日后的維護成本是大大的降低,尤其在沒有使用Sass,Less,Styus這些預編譯工具的情況下。
并且,CSS書寫的工作量以及CSS代碼量那都是明顯下降啊,并且HTML層面代碼更加精簡直白,超好記憶。要知道,HTML代碼后期往往可能就是開發人員維護了,除非你文檔寫得好,否則開發人員怎么知道按鈕換個顏色要怎么辦?但是你走顏色關鍵字的獨立類名,完全不會CSS的開發人員他也能輕松維護啊。
總而言之,各種爽各種舒暢!
幾個顏色類名搞定了下面30多個不同顏色不同風格的靜態UI控件,可以說少了上百行CSS代碼都不為過:
最后,再提一句,本策略能夠實現的重點技巧就是利用 ::first-line 偽元素的文字控色技術。
三、技術發展與思維轉換
技術的發展往往會帶來相應的思維方式上的轉變,這樣才能相輔相成,發揮新技術的潛力,如果還是使用以前的思維模式,怎么說呢,有著勞斯萊斯加著92#汽油在跑的感覺。
weui中按鈕的CSS書寫就是典型的傳統實現策略,扎實而穩固,傳統最佳實踐的遺留產物。
因為畢竟PC是先發展的,由于技術的限制,我們的思維也被限制了。
例如,由于IE6瀏覽器對 .a.b 這種級聯類名樣式支持有嚴重bug,同時考慮到其效率在選擇器中排很后,因此,很長一段時間里,我們對于按鈕的樣式的覆蓋策略都不是基于狀態,而是基于完整的按鈕類名+狀態類名的這種方式,因為可以很好地支持IE6,且幾乎不可能發生沖突。
放到顯示世界,大部分的項目都是自成體系,不會和其他項目直接參雜在一起,因此,可以適當降低考慮沖突的風險;第二,很多項目寫頁面的就一個人,由于不要擔心會遇到黃油手同事,所以,只要自己嚴格按照準則來書寫,則簡單的代碼和快速的書寫帶來的收益會更高。
再例如,由于 currentColor 變量IE9瀏覽器才支持,所以,長期的PC項目開發并沒有讓重構同學意識到我們現在再做移動端項目的時候,可以直接通過一個 color 屬性,改變按鈕或者圖標或者標簽的顏色而樣式不亂。如果這個世界先出現移動端,再出現PC端,我想,我們靜態UI組件的書寫策略可能就會如本文所言,基于 color 屬性的系統和貫穿書寫,而非來一槍打一炮的這種游擊策略。
換句話說,雖然CSS3技術帶來了很多很棒的東西,但是,我們的思維方式卻似乎還停留在老PC時代,或許是因為關注的僅僅是CSS3表面的那點特性表現的緣故吧。
四、基于CSS color重構UI組件適用項目和場景
沒有哪一種策略是一方通行的,本文的 color 策略雖然精妙且好處多多,但同樣有其局限性。
首先是 兼容性限制 ,技術關鍵點之一 currentColor IE9+瀏覽器才支持,因此,目前適用于移動端開發,以及一些不需要管低版本IE瀏覽器的項目。雖然瀏覽器的進步,相信不需要多久,PC項目也能看到這種策略的慢慢普及。
其次, 不適用于開源項目 。開源意味著會和其他眾多使用者的項目混在一起,我們自己團隊中開發,自然會有規范約束,但是一旦魚龍混雜在一起,則,類似 .red 這樣的短命名類名很容易被其他樣式中 .red 類名給沖掉。因此,從這一點來看,weui的實現策略實際上是最合適的,使用本文的 color 屬性策略反而會容易被提issues,但是,細節上可以再完善,例如:
.weui-btn_plain-default {
color: #353535;
border: 1px solid #353535;
}
.weui-btn_plain-primary {
color: #1aad19;
border: 1px solid #1aad19;
}
可以直接寫成:
.weui-btn_plain-default {
color: #353535;
border: 1px solid;
}
.weui-btn_plain-primary {
color: #1aad19;
border: 1px solid;
}
繼而, border:1px solid 可以放在基礎樣式中,因此,CSS進一步縮減為:
.weui-btn_plain-default {
color: #353535;
}
.weui-btn_plain-primary {
color: #1aad19;
}
看到沒,本質上就是個 dark 和 green 兩個顏色類名。
五、沒有結語總覺得怪怪地
可是人困眼乏,想不到該吐槽什么東西,早年嘛前一篇文章已經拜過了。
來自:http://www.zhangxinxu.com/wordpress/2016/11/development-ui-component-based-on-css-color/