趣味横生的复选框状态样式

Avatar of Preethi
Preethi

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

我们可能会让文本输入保持无样式。我们可能会让链接保持无样式。甚至按钮也是如此。但复选框……我们不会放任不管。这就是为什么复选框样式永不过时。

尽管设计复选框并不复杂,但我们也不必满足于简单的背景颜色更改或添加和删除边框来指示状态更改。我们也不必使用任何我们不具备的花哨设计技巧来完成这项工作。我将向您展示如何操作。

基础知识

在以下演示中,复选框几乎都具有相同的三个堆叠布局——底部是复选框,在其顶部是两个堆叠的元素或伪元素。根据哪个元素可见,复选框被指示为选中或未选中。

如果您查看笔中的 CSS 代码,您会注意到所有布局(包括复选框的布局)都是网格。您可以使用适合您的用例的其他布局(并在 CSS-Tricks 网格指南 中了解更多信息)。有关代码和设计替代方案的其他说明位于笔内源代码的末尾。

此外,堆叠在复选框顶部的任何元素都具有 pointer-events: none,因此它们不会阻止用户点击或点击复选框。

现在让我们来看第一种方法。

方案 1:混合背景作为状态

CSS 中的混合是一种多功能技术。相对于两个或多个元素或背景操作颜色在您可能从未想到的上下文中非常方便。

复选框就是一个这样的例子。

<input id="un" type="checkbox"> <label for="un">un</label>
<!-- more checkboxes --> 
input[type=checkbox]::before,
input[type=checkbox]::after {
  mix-blend-mode: hard-light;
  pointer-events: none;
  /* more style */
}
input[type=checkbox]::before {
  background: green;
  content: '✓';
  color: white;
  /* more style */
}
input[type=checkbox]::after {
  background: blue;
  content: '⨯';
  /* more style */
}
input[type=checkbox]:checked::after {
  mix-blend-mode: unset;
  color: transparent;
}

在此演示中,我将复选框的伪元素设置为绿色和蓝色,将它们堆叠起来,并分别为它们提供了 mix-blend-mode 值。这意味着每个元素的背景与其背景混合。

我使用了 hard-light 值,它模拟了 multiplyscreen 的结果,具体取决于顶部颜色是深色还是浅色。您可以在 MDN 上深入了解 不同的混合模式

选中该框时,::after 伪元素的混合模式值将被取消设置,从而产生不同的视觉效果。

方案 2:制作 3D 动画

为彩色块制作动画很有趣。让它们看起来是 3D 的,效果会更好。CSS 有能力沿着模拟的 3D 空间渲染元素。因此,使用它,我们制作一个 3D 盒子并将其旋转以指示复选框状态更改。

<div class="c-checkbox">
  <input type="checkbox" id="un">
  <!-- cube design -->
  <div><i></i><i></i><i></i><i></i></div>
</div>
<label for="un">un</label>
<!-- more checkboxes -->
.c-checkbox > div {
  transition: transform .6s cubic-bezier(.8, .5, .2, 1.4);
  transform-style: preserve-3d;
  pointer-events: none;
  /* more style */
}
/* front face */
.c-checkbox > div > i:first-child {
  background: #ddd;
  transform:  translateZ( -10px );
}
/* back face */
.c-checkbox > div > i:last-child {
  background: blue;
  transform:  translateZ( 10px );
}
/* side faces */
.c-checkbox > div > i:nth-of-type(2),
.c-checkbox > div > i:nth-of-type(3) {
  transform: rotateX(90deg)rotateY(90deg);
  position: relative;
  height: 20px;
  top: 10px;
}
.c-checkbox > div > i:nth-of-type(2) {
  background: navy;
  right: 20px;
}
.c-checkbox > div > i:nth-of-type(3) {
  background: darkslategray;
  left: 20px;
}

复选框后的 <div> 成为 3D 空间的容器——在赋予其 transform-style: preserve-3d; 后,其子元素可以沿 x、y 和 z 轴放置。

使用 transform 属性,我们在 z 轴上放置两个 <i> 元素(灰色和蓝色),并在它们之间留出一些距离。另外两个夹在它们之间,覆盖它们的左右两侧。它就像一个除了顶部和底部都被覆盖的纸板箱。

选中复选框时,此灰色和蓝色盒子会侧向旋转以面向另一侧。由于我已经向 <div> 添加了 transition,因此它的旋转是动画化的。

input:checked + div { 
  transform: rotateY( 180deg ); 
}

方案 3:使用边框半径

更改选中框的边框半径?没那么有趣。也更改附近其他框的边框半径?现在我们有了一些东西。

<input type="checkbox" id="un"> <label for="un">un</label>
<!-- more rows of checkboxes -->
input {
  background: #ddd;
  border-radius: 20px;
  /* more style */
}
input:not(:first-of-type)::before {
  content: '';    
  transform: translateY(-60px); /* move up a row */
  pointer-events: none;
}
input:checked + * + input::before,
input:last-of-type:checked {
  border-radius: 20px;
  background: blue;
}
input:checked + * + input:checked + * + input::before {
  border-top-left-radius: unset !important;
  border-top-right-radius: unset !important;
}
input:checked::before {
  border-bottom-left-radius: unset !important;
  border-bottom-right-radius: unset !important;
}
/* between the second-last and last boxes */ 
input:nth-of-type(4):checked + * + input:checked {
  border-top-left-radius: unset;
  border-top-right-radius: unset;
}

如果您之前刚刚与演示互动过,您会注意到,当您点击或点击复选框时,它不仅可以更改自己的边框,还可以更改其后之前的框的边框。

现在,我们没有可以选择前面元素的选择器,只有可以选择后面元素的选择器。因此,我们为了控制前面框的外观所做的事情是使用复选框的伪元素来设置前面框的样式。除了第一个框之外,每个其他框都会得到一个伪元素,该伪元素被移动到其前面框的顶部。

假设框 A、B 和 C 是一个接一个的。如果我点击 B,我可以通过设置 B 的伪元素的样式来更改 A 的外观,通过设置 C 的伪元素的样式来更改 B 的外观,并通过设置 D 的伪元素的样式来更改 C 的外观。

从 B 开始,可以访问 B、C 和 D 的伪元素——只要下一个元素选择器可以在布局中它们之间使用。

每个复选框的四个角在选中和未选中时最初都是圆角的。但是,如果选中一个框,则下一个框的顶部角和前面框的底部角将变直(通过覆盖和移除它们的边框半径)。

方案 4:使用 CSS 蒙版

切换按钮……就代码而言,它们也是复选框。因此,我们可以将这些框样式化为切换按钮,并且它是使用 CSS 蒙版完成的,Chris 之前写过这方面内容。但简而言之,这是一种使用图像过滤其背景部分的技术。

<input type="checkbox">
<div class="skin one"></div>
<div class="skin two"></div>
.one.skin {
  background: no-repeat center -40px url('photo-1584107662774-8d575e8f3550?w=350&q=100');
}
.two.skin {
  background: no-repeat center -110px url('photo-1531430550463-9658d67c492d?w=350&q=100');
  --mask: radial-gradient(circle at 45px 45px , rgba(0,0,0,0) 40px, rgba(0,0,0,1) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);
}

两个皮肤(显示风景照片)位于复选框的顶部。最上面的一个获取了一个形状为典型切换按钮的 mask-image——左侧是一个透明的圆圈,其余部分是完全不透明的颜色。通过透明圆圈,我们可以看到下面的照片,而其余的蒙版图像则显示顶部的照片。

点击复选框时,透明圆圈将移至右侧,因此我们通过圆圈看到顶部的图像,而其余部分则显示底部的照片。

input:checked ~ .two.skin {
  --mask: radial-gradient(circle at 305px 45px, rgba(0,0,0,1) 40px, rgba(0,0,0,0) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);
}

方案 5:使用盒子阴影

最后,让我们来看最简单——但我认为也是最有效——的方法:动画内阴影 box-shadow

<input id="un" type="checkbox"> <label for="un">un</label>
input {
  transition: box-shadow .3s;
  background: lightgrey;
  /* more style */
}
input:checked { 
  box-shadow: inset 0 0 0 20px blue;
}

有一些 CSS 属性可以默认进行动画处理,其中之一就是 box-shadow。这种类型的细微动画非常适合极简主义主题。


就是这样!我希望这能激发您下次处理复选框时的灵感。CSS 为我们提供了许多指示状态更改的可能性,所以尽情享受乐趣,如果您有任何有趣的想法,请分享。