akira-cn / FE_You_dont_know

分享在前端开发中,你不知道的JavaScript、CSS和HTML趣味知识,增加你的知识面。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

巧用currentColor属性来实现自定义checkbox样式

akira-cn opened this issue · comments

commented

在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 class="item" 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" style="enable-background:new 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中留言讨论~

commented

好像利用 outline 也能实现

li:hover input[type=checkbox] {
  outline: 10px solid red !important;
  outline-offset: -10px;
}

input[type=checkbox] {
  position: relative;
  color: inherit;
  outline:10px solid #008080;
  outline-offset: -10px;
}

li:nth-child(2n + 1) input[type=checkbox] {
  position: relative;
  color: inherit;
  outline:10px solid #000080;
  outline-offset: -10px;
}

https://codepen.io/BeAce/pen/mNrjBY

commented

outline是可以的,不过outline不好实现圆角,用伪元素实现更灵活。

另外outline也可以利用currentColor,没有必要写三条规则,代码可以直接简化成:

input[type=checkbox] {
  position: relative;
  color: inherit;
  outline:10px solid;
  outline-offset: -10px;
}

直接这样就行了。

commented

outline是可以的,不过outline不好实现圆角,用伪元素实现更灵活。

另外outline也可以利用currentColor,没有必要写三条规则,代码可以直接简化成:

input[type=checkbox] {
  position: relative;
  color: inherit;
  outline:10px solid;
  outline-offset: -10px;
}

直接这样就行了。

受教了