如何更好的控制按鈕樣式
在Web頁面或應用程式中都可能會有按鈕的出現,甚至很多時候連結的樣式看起來也像個按鈕。那麼我們應該怎麼來美化按鈕的樣式呢?在這篇文章中,我們一起來聊聊按鈕樣式應該怎麼才能更好的控制。
重置按鈕的樣式
平時在Web中新增一個按鈕,大多數的時候都會使用<a>
、<button>
標籤,也有的時候會使用<input type="button">
。隨著移動端的出現,更多的人喜歡使用<div>
標籤來新增按鈕,而事實上,HTML中的任何一個標籤元素都可以是用來寫一個按鈕。雖然寫一個按鈕的標籤元素沒有過嚴格的要求,不過個人更建議寫按鈕的時候採用<a>
標籤或者<button>
標籤,出於這樣的考慮主要還是因為標籤的語義化來做的考慮。
至於在Web中應該使用<a>
還是<button>
標籤或者說其他的HTML標籤來寫一個按鈕呢?在社群也有過相應的討論,只不過在這篇文章中不想做過多的闡述,如果你感興趣的話,可以花點時間閱讀下面幾篇文章:
- ofollow,noindex" target="_blank">Links vs. Buttons in Modern Web Applications
- Anchors vs Buttons
- The Difference Between Anchors, Inputs and Buttons
- But sometimes links look like buttons (and buttons look like links)
事實上,在Web網站或應用程式中近99.9%
的可點選內容都是<a>
或<button>
元素。如果你不確定在給定的情況下應該使用什麼元素的話,可以參考下面的建議:
-
如果需要跳轉到新的頁面或更改頁面的大部分內容,建議使用
<a>
元素 -
否則,更建議使用
button
元素(或者<input type="button">
)
為什麼要這麼用呢?主要是出於HTML的語義化做考量,而且這樣做更有利於SEO。除此之外也能更好的配合鍵盤做相應的操作,更利於提高使用者的可訪問性。儘管如此,開發人員很少使用<button>
元素。特別是在移動端的開發中,更多的開發人員更喜歡使用<div>
、<span>
或<a>
這樣的元素。
為什麼會有這方面的現象呢?主要是因為:
<button>
元素帶有複雜的預設樣式(特別是在不同的瀏覽器中略有不同)
,這樣一來也增加了樣式難於維護。幸運的是,我們可以在reset.css
樣式檔案中重置<button>
的樣式,讓所有客戶端初始的樣式更趨於統一,也更利用按鈕樣式的美化:
button { padding: 0; border: none 0; font: inherit; color: inherit; background-color: transparent; cursor: pointer; }
這樣一來,按鈕在Web上看上去就像是一個文字。像下圖這樣:
這樣做,雖然樣式上在不同的客戶端趨於統一(看上去更像文字)。但這樣一來,我們就必須對所有按鈕新增樣式,否則使用者將無法識別它們。
給按鈕新增樣式
現在我們已經重置了<button>
元素在各客戶端下的樣式,讓他們都趨於統一。但按鈕畢竟是按鈕,和文字是不一樣的(樣式上看上去應該是不一樣的),因此我們就需要給其新增自己定義樣式(根據你的需求來新增)。比如下面這樣的示例程式碼:
.btn { display: inline-flex; justify-content: center; align-items: center; text-decoration: none; /*for <a> link*/ margin: 2px; border: 1px solid transparent; border-radius: 4px; padding: .5em 1em; color: #fff; background-color: #9555af; }
這樣一來,不管是<a>
元素或者是<button>
元素,甚至是其他的HTML標籤,比如div
標籤,最終的效果都統一了,可能類似於下圖這樣的效果:
對於按鈕顏色的控制,更應該根據自己的設計需求(使用者的需要)做相應的裝置。
正如上圖所示,現在看上去像一個按鈕了,但僅僅是一種狀態。而事實上呢?Web頁面或Web應用程式上的按鈕除了預設狀態樣式之外,還有:hover
、:focus
和:active
等狀態。這樣一來按鈕的互動行為更全,按鈕看上去也更漂亮。
其實客戶端,比如瀏覽器已經為<button>
的focus
和active
狀態提供了預設樣式,只不過我們在重置按鈕樣式的時候把這些樣式也重置了。如果為了和設計相匹配,我們需要為這些狀態新增樣式:
.btn:focus, .btn:active { outline: none 0; transform: translateY(1px); filter: saturate(150%); } .btn:hover { color: #9555af; border-color: currentColor; background-color: #fff; }
這個時候按鈕的樣式更為豐富,效果看起來像下圖這樣:
前背景自動配色
前背景自動配色指的是按鈕的color
值會根據background-color
做出相應的調整。比如說,
根據background-color
將color
換成black
或white
。另外對於border-color
也可以應用同樣的邏輯。這樣做的話,讓我們的按鈕更具可視性,也更易於維護和打理。
實現這樣的一個效果,最簡單的方法就是使用CSS的HSL
來設定顏色的值,並且同時藉助CSS自定義的特性,讓事情變得更簡單些。具體實現的時候,我們可以這樣做:
-
在
:root
分別定義三個變數--hue
(HSL
中的H
)、--saturation
(HSL
中的S
)和--light
(HSL
中的L
) -
使用
HSL
方式來設定background-color
這樣就可以非常簡單的確定亮度並將其作為條件語句的基礎:
:root { --hue: 220; --saturation: 90; --light: 36; } .btn { background-color: hsl(var(--hue), calc(var(--saturation) * 1%), calc(var(--light) * 1%)); }
這個時候看起來像下圖這樣:
CSS自定義屬性提供的API:style.setProperty()
,藉助<input>
我們可以很好的做一些動態計算,這樣可以很好的看到修改三個自定義屬性時,對按鈕背景顏色的變化:
上面Demo所看到的僅僅是對按鈕背景顏色的調整,但還沒有達到我們所需要的要求,按鈕的color
會根據background-color
做相應的調整。不過不用擔心,為了達到想要的目標,我們繼續往下閱讀。
前面提到過,自從引入CSS自定義屬性以來,我們就得到了附帶的條件語句。這個技巧是基於一些CSS引數被限制為最小值和最大值 。簡單地說:
CSS屬性值超過正常的範圍的時候,只要格式正確,就會正常的渲染,而這個渲染的值只是其合法的邊界值,即:CSS的最小值和最大值 。
比如CSS中的opacity
這個屬性,我們都知道這個屬性值的合法範圍是0 ~ 1
之間,而在實際使用的時候,就算是你設定了小於0
或者大於1
的值時,瀏覽器也能正常的渲染,只不過其被渲染的值要麼是0
,要麼是1
。比如:
.demo { opacity: -1; /* 被渲染成 0*/ opacity: 2; /* 被渲染成 1*/ }
除了這個屬性值之外,CSS中還有一些屬性值也有類似的特性,比如顏色中的RGB
,它們的範圍就是0~255
;HSL
中的H
是0 ~ 360
,S
和L
是1 ~ 100
。這樣一來,我們就可以把這樣的特性應用到我們的按鈕設定中(完成背景顏色和文字顏色切換)。還是拿HSL
設定顏色為例,將任何負值限制為0
(不管色相和飽和度如何,結果是黑色);將任何大於100%
的值限制為100%
(總是白色)。
如此一來,我們可以從亮度(--light
)引數中減去所需的閾值(也就是臨界值,這個值一般設定在50 ~ 70
之間),這個閾值用--threshold
來表示,然後再乘以100%
,這樣做就可以讓其超過其中一個限制,要麼小於0
,要麼大於100%
。因為我們需要負的結果用白色表示,正的結果用黑色表示,所以還要把其結果反過來,因此我們可以乘以一個-100%
。將程式碼稍微調整一下:
:root { --light: 80; --threshold: 60; } .btn { --switch: calc( (var(--light) - var(--threshold)) * -100% ); color: hsl(0, 0%, var(--switch)); }
這個時候調整--light
的值時,按鈕的color
會隨著background-color
在black
和white
之間進行切換。如下圖所示:
上圖效果中我們不難發現,當按鈕的背景顏色太亮時(趨於白色),在主體背景顏色和按鈕背景顏色相近時,我們的按鈕看上去又像是一個文字了,似乎回到了按鈕重置樣式之初了:
為了提供一個更好的使用者體驗,我們可以使用上述同樣的原理來給按鈕設定border-color
。那麼我們就需要一個邊框顏色的閾值,即:
--border-threshold
,一般情況設定為80
:
:root { --border-threshold: 80; } .btn { --border-light: calc(var(--light) * 0.7%); --border-alpha: calc((var(--light) - var(--border-threshold)) * 10); border-color: hsla(var(--hue), calc(var(--saturation) * 1%), var(--border-light), var(--border-alpha)); }
這個時候,整個按鈕的效果更接近於我們的目標了,如下圖所示:
當然,你也可以直接在下面的這個Demo體驗一下:
整體的關鍵程式碼如下:
:root { --hue: 220; --saturation: 90; --light: 36; --threshold: 60; --border-threshold: 80; } .btn { --switch: calc( (var(--light) - var(--threshold)) * -100% ); --border-light: calc(var(--light) * 0.7%); --border-alpha: calc((var(--light) - var(--border-threshold)) * 10); color: hsl(0, 0%, var(--switch)); background-color: hsl(var(--hue), calc(var(--saturation) * 1%), calc(var(--light) * 1%)); border-color: hsla(var(--hue), calc(var(--saturation) * 1%), var(--border-light), var(--border-alpha)); }
上面我們是使用hsl
來設定按鈕的相關顏色。其實使用RGB
設定按鈕元素有關於顏色部分的屬性值也是可以的,這裡會用到一些顏色計算的公式,即:
使用RGB
中的R
、G
和B
分別乘以相關係數模擬出一個L
。這裡分別會用到
sRGB Luma
和
W3C方法
演算法(公式):
根據類似的做法,我們可以這樣來擼碼:
:root { --red: 128; --green: 40; --blue: 220; /* 閾值範圍`0 ~ 1`,建議取值`0.5 ~ 0.6`之間*/ --threshold: .6; /*閾值範圍: `0 ~ 1`,建議取值`0.8+`*/ --border-threshold: 0.8; } .btn { /*使用sRGB Luma公式計算L*/ --r: calc(var(--red) * 0.2126); --g: calc(var(--green) * 0.7152); --b: calc(var(--blue) * 0.722); --lightness: calc((var(--r) + var(--g) + var(--b)) / 255); --border-alpha: calc((var(--lightness) - var(--border-threshold)) * 100); background-color: rgb(var(--red), var(--green), var(--blue)); color: hsl(0, 0%, calc((var(--lightness) - var(--threshold)) * -10000000%)); border-color: rgba(calc(var(--red) - 50), calc(var(--green) - 50), calc(var(--blue) - 50), var(--border-alpha)); }
有關於這方面更詳細的介紹可以閱讀 @張鑫旭 老師的博文《CSS前景背景自動配色技術簡介 》。
設定二級按鈕樣式
在很多CSS Frameworks中有關於按鈕的元件都會有二級按鈕的樣式風格。比如大家熟知的Bootstrap,它的二級按鈕樣式風格長得如下圖所示:
在按鈕系統中二級按鈕與主按鈕唯一不同的就是背景顏色上的差異。大多時候,通過另外一個類名,比如btn-secondary
,給其設定一個background-color
。
前面我們提到過,通過HSL
或RGB
顏色值,並且藉助
sRGB Luma
和
W3C方法
演算法控制按鈕背景色和文字色。如果我們想基於這個系統上來完成二級按鈕樣式顏色控制話。我們應該如何做呢?
實現這一目標我們可以通過以下兩種方式來實現:
-
filter: hue-rotate(60)
:通過濾鏡來完成,但這種方式會影響其子元素的顏色 -
HSL hue + 60
:重新計算
--h
變數值,在--hue
值基礎上增加60
。因為HSL
中的H
(其實就是Hue)引數在360
時沒有封頂這樣的行為。因為它的行為類似一個角度,所以值超過360
時並不會一直停留在該位置。比如說400
,其實相當於40
(400 - 360 = 40
)
這樣一來,只需在.btn-secondary
上重置--h
的值:
.btn-secondary { --h: calc(var(--hue) + 60) }
其實除了上述的方式之外,還可以使用color-mod()
函式來修改顏色。只是目前該屬性可用性還不足夠好。如果你感興趣的話,不仿閱讀《
使用color-mod()
函式修改顏色
》一文。
總結
按鈕在Web應用程式中是最為常見的一種元件,避免不了對按鈕寫樣式。而這篇文章介紹如何給按鈕寫樣式,又應該如何正確的給按鈕寫樣式。並且在後文中根據
sRGB Luma
和
W3C方法
演算法,藉助HSL
、RGB
以及CSS自定義屬性,實現按鈕background-color
和color
自動切換等效果。