Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
akira-cn opened this issue Jul 22, 2019 · 3 comments
Open

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

akira-cn opened this issue Jul 22, 2019 · 3 comments

Comments

@akira-cn
Copy link
Owner

在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中留言讨论~

@Beace
Copy link

Beace commented Jul 26, 2019

好像利用 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

@akira-cn
Copy link
Owner Author

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

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

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

直接这样就行了。

@Beace
Copy link

Beace commented Jul 27, 2019

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

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

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

直接这样就行了。

受教了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants