0%

自定义多选框

今天看了一个做 Todo List 的视频,学了一招,可以自定义多选框的样式,只用 CSS 就可以做到。

整个的思路大概是:隐藏 input 元素,在 label 下用伪元素实现一个自定义的多选框。

起步

先写一些关于表单最基础的 HTML 和 CSS。

下面的 HTML 表单允许你选择多个颜色:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<form>
<fieldset>
<legend>Choose Your Color</legend>
<ul>
<li>
<input type="checkbox" name="red" id="red" />
<label for="red">red</label>
</li>
<li>
<input type="checkbox" name="green" id="green" />
<label for="green">green</label>
</li>
<li>
<input type="checkbox" name="yellow" id="yellow" />
<label for="yellow">yellow</label>
</li>
<li>
<button type="submit">Submit</button>
</li>
</ul>
</fieldset>
</form>

清除 ul 的默认样式:

1
2
3
4
5
ul {
list-style: none;
margin: 0;
padding: 0;
}

表单完成了,接下来进入正题。

隐藏 input

首先我们要隐藏原生的 input

1
2
3
input[type="checkbox"] {
display: none;
}

这确实隐藏了元素,但你觉得这样对吗?

哈哈,其实在这里使用 display: none 是不对的,因为对那些使用 Tab 浏览网页的人,这些 input 就永远无法被选中了。

所以我们要用另一种方式:

1
2
3
4
input[type="checkbox"] {
position: absolute;
opacity: 0;
}

我们用 position: absolute 把它移出 Document flow,再把它变透明,这样我们虽然看不到它,但用 Tab 依然可以 focus 它。

自定义多选框

默认的多选框已经被移走了,现在我们要添加自定义的多选框了,我们应该把自定义的多选框添加在 label 里面,这样有许多好处,比如选择器 label:hover 可以选择到我们的多选框的父元素,还有许多好处,随着接下来的实现过程你可以慢慢体会到。

我们可以通过伪元素添加自定义多选框:

1
2
3
4
5
6
7
8
9
label::before {
--length: 0.7em;
content: "";
display: inline-block;
width: var(--length);
height: var(--length);
border: 1px solid black;
margin-right: var(--length);
}

这里的 --length 是局部 CSS 变量,即不在 :root 上定义的变量,这样可以限定它的作用域,它表示多选框的边长。

可以用 flexbox 让多选框和文字对齐:

1
2
3
4
label {
display: flex;
align-items: center;
}

当然,现在这个多选框还不能用,我们需要让被隐藏的多选框处于 checkedfocus 状态时,自定义多选框可以有合适的样式,当 labelhover 时,自定义多选框可以有合适的样式。

1
2
3
4
5
input[type="checkbox"]:checked + label::before {
background-color: tomato;
box-shadow: inset 0 0 0 1px white;
border-color: tomato;
}

上面的 CSS 表示当隐藏多选框处于 checked 状态时,给自定义多选框改一个背景颜色和边框颜色,并用 inset box-shadow 来做一个类似原生 radio 被选中的效果。

1
2
3
4
5
label:hover::before,
input[type="checkbox"]:focus + label::before {
transform: scale(1.2);
border-color: tomato;
}

上面的 CSS 表示当隐藏多选框被 focuslabelhover 时,将自定义多选框放大,并修改他的 border-color 来实现正确的视觉效果。

最后再往自定义多选框上加一些渐变就更好看了:

1
2
3
label::before {
transition: transform 0.1s, background-color 0.1s, box-shadow 0.1s;
}

结尾

你可以根据你的网页风格改变自定义多选框的样式。

奥里给,老铁们,干了!