巧用 currentColor 屬性來實現自定義 checkbox 樣式

語言: CN / TW / HK

在 CSS3 中,有一個常被忽視的顏色屬性值,叫做 “currentColor”。

它可以作為屬性值作用於元素的 color、background-color、border 等屬性中,也可以作用於 SVG 和 Canvas。

currentColor 的語義是表示將顏色設為當前文字顏色,在有些特定的場景下,這個特殊的屬性值能給我們帶來很大的方便。

比如下面的這個例子。

我們知道,使用 CSS 是沒辦法直接定義 checkbox 元素的 color 和 background-color 屬性的。因此,如果我們想要改寫 checkbox 的樣式,就需要用別的辦法。

input[type=checkbox] {
  background-color: red;
  color: red;
  border: solid red;
}

複製代碼

上面的屬性設置對 checkbox 的外觀統統不起作用

對於 CSS 經驗比較豐富的同學,很容易想到,一種比較優雅的方式是採用偽元素。

我們看一下我要實現的 checkbox 的效果:

我在一個列表項中實現 checkbox,讓 checkbox 的顏色隨着列表項的文字顏色改變,一共有三種不同顏色,奇數行默認的顏色是藍色,偶數行默認的顏色是青色,鼠標 hover 上的列表項,顏色為紅色。

checkbox 選中時,表現為中心一個白色的 x。

它的 HTML 結構如下:

<ul>
  <li><input type="checkbox">第1項</li>
  <li><input type="checkbox">第2項</li>
  <li><input type="checkbox">第3項</li>
  <li><input type="checkbox">第4項</li>
  <li><input type="checkbox">第5項</li>
  <li><input type="checkbox">第6項</li>
</ul>

複製代碼

那麼我們可以來定義一下樣式:

首先是列表的樣式

ul {
  padding: 0;
}

li {
  color: #008080;
  list-style: none;
}

li:nth-child(2n + 1) {
  color: #000080;
}

li:hover {
  color: red;
}

複製代碼

然後定義 checkbox 的樣式:

input[type=checkbox] {
  position: relative;
  color: inherit;
}

input[type=checkbox]::before,
input[type=checkbox]::after {
  position: absolute;
  display: inline-block;
  width: 12px;
  height: 12px;
  line-height: 12px;
  border-radius: 3px;
  text-align: center;
}

input[type=checkbox]:checked::after {
  content: 'x';
  color: white;
}

input[type=checkbox]::before {
  content: ' ';
  background-color: currentColor;
}

複製代碼

如上面代碼,基本思路是,我們用 before 偽元素實現 checkbox 的背景,用 after 偽元素實現選中時白色的 “x”。

在這裏,我們注意 currentColor 的用法:

input[type=checkbox]::before {
  content: ' ';
  background-color: currentColor;
}

複製代碼

我們將 checkbox 的 before 偽元素的 background-color 設置為 currentColor,表示將背景色設置為當前的文字顏色值。不過要注意,偽元素在 DOM 樹中是渲染成對應元素的子元素,所以此時checkbox::before的 background-color 的值應該是 checkbox 的文字顏色,即 color 屬性值。

但是,checkbox 默認的 color 值並不會繼承它的父元素,也就是這裏的 li,所以我們要先將 checkbox 的 color 值設置為繼承父元素:

input[type=checkbox] {
  position: relative;
  color: inherit;
}

複製代碼

👉🏻 知識點:將 CSS 屬性值設置為inherit,能夠讓元素從父元素繼承該屬性值。

👉🏻 知識點:將 background-color 屬性設置為 currentColor,能夠讓元素的 background-color 呈現為當前的文字顏色,即 color 屬性值。

checkbox::before的 color 屬性值默認繼承 checkbox 的 color 屬性值,所以這樣我們就將它的background-color設置為文字的屬性值了。

最後完整的例子在這裏

擴展

border-color屬性的默認值是currentColor,因此,如果你要將一個元素的邊框顏色設置為與文字顏色相同,可以缺省border-color屬性值,例如:

div {
  color: red;
  border: solid 1px;
}

複製代碼

相當於

div {
  color: red;
  border: solid 1px currentColor;
}

複製代碼

currentColor 對 SVG 元素的 fill 和 stroke 屬性同樣有效,因此我們可以用它簡單實現 SVG icon 隨着文字顏色變化而變化。

例如:

在線演示

<a href="###">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 22 22" xml:space="preserve">
    <g>
      <path d="M9.7,14.4L9.7,14.4c-0.2,0-0.4-0.1-0.5-0.2l-2.7-2.7c-0.3-0.3-0.3-0.8,0-1.1s0.8-0.3,1.1,0l2.1,2.1l4.8-4.8c0.3-0.3,0.8-0.3,1.1,0s0.3,0.8,0,1.1l-5.3,5.3C10.1,14.3,9.9,14.4,9.7,14.4z"></path>
    </g>
  </svg>
  <span>工作任務</span>
</a>

複製代碼
a {
  text-decoration: none;
}

a:link,
a:visited {
  color: #37c;
}

a:hover,
a:active {
  border-bottom: dashed;
  color: red;
}

.item svg {
  width: 32px;
  height: 32px;
  vertical-align: middle;
  fill: currentColor;
}

複製代碼

currentColor 屬性就介紹到這裏,這個屬性在工作中還有什麼具體用途?歡迎在 issue 中留言討論~