一个元素纯CSS实现开关按钮【介绍box-shadow、单边或多重阴影、appearance属性】

2,047 阅读6分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情

借助checkbox表单元素、:checked伪类、::before/::after伪元素,就可以只需一个input[type="checkbox"]元素,通过纯CSS实现Switch开关效果的按钮。

主要用到的属性:

  • appearance 默认css元素样式
  • box-shadow 阴影效果
  • transition css动画过渡属性

实现过程

  • 添加一个input元素
<input class="switch-button" type="checkbox">
  • 基本样式
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body{
    background-color: #e3a380;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}
  • appearance设置浏览器默认的input[type="checkbox"]元素样式为none,即无样式。

设置outline: none;,有的浏览器在设置无样式后,仍会有外线框效果(和border不太一样),需要去除。

box-shadow给一个很淡的内层阴影。

.switch-button{
    position: relative;
    width: 80px;
    height: 40px;
    border-radius: 20px;
    appearance: none;
    background-color: #c6c6c6;
    outline: none;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, .2);
    transition: .5s;
}

可以看一下添加内层阴影后的不同。

  • :checked伪类设置input[type="checkbox"]选中后背景颜色修改为蓝色。
.switch-button:checked{
    background-color: #03a9f4;
}

  • 添加一个before伪类,绝对定位,样式为白色的圆点。添加外侧底部阴影。
.switch-button::before{
    content: '';
    position: absolute;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    top: 0;
    left: 0;
    background-color: #fff;
    box-shadow: 0 2px 5px rgba(0, 0, 0,/3);
    transition: .5s;
}

  • transform: scale(1.1);transform: scale(.9); 放大或缩小圆点按钮

  • :checked选中时移动圆点按钮的位置
.switch-button:checked:before{
    left: 40px;
}

选中时。

  • 看一下.switch-button不设置背景的效果,将使用父元素的背景颜色。
.switch-button{
    background-color: unset;
}

或者不指定background-color属性。

appearance属性

appearance表示浏览器的默认样式,其具体样式依据的是操作系统。

The appearance CSS property is used to control native appearance of UI controls, that are based on operating system's theme.

appearance 属性允许设置元素显示为浏览器提供的标准界面。

比如:

appearance: normal|icon|window|button|menu|field;

● normal:正常呈现元素

● icon:作为一个小图片来呈现元素。

● window:作为一个视口来呈现元素。

● button:作为一个按钮来呈现元素。

● menu:作为一个用户选项设定来呈现元素选择。

● field:作为一个输入字段来呈现元素。

appearance可参考的设置值如下,更多或详细介绍参见 MDN appearance

/* CSS Basic User Interface Module Level 4 values */
appearance: none;
appearance: auto;
appearance: menulist-button;
appearance: textfield;

/* "Compat-auto" values, which have the same effect as 'auto' */
appearance: button;
appearance: searchfield;
appearance: textarea;
appearance: push-button;
appearance: slider-horizontal;
appearance: checkbox;
appearance: radio;
appearance: square-button;
appearance: menulist;
appearance: listbox;
appearance: meter;
appearance: progress-bar;

/* Partial list of available values in Gecko */
-moz-appearance: scrollbarbutton-up;
-moz-appearance: button-bevel;

/* Partial list of available values in WebKit/Blink (as well as Gecko and Edge) */
-webkit-appearance: media-mute-button;
-webkit-appearance: caret;

/* Global values */
appearance: inherit;
appearance: initial;
appearance: revert;
appearance: revert-layer;
appearance: unset;

box-shadow 阴影效果

box-shadow

box-shadow用于设置元素的阴影效果,如果要设置多个阴影效果,需要用逗号,分开。

box-shadow: <offset-x> <offset-y> <blur-radius> <spread-radius> <color>;

box-shadow属性值的含义依次为:阴影的 X 轴偏移量、Y 轴偏移量、模糊半径、扩散半径(扩展半径)和颜色。以及一个可选的inset值(一般放最前面),表示内层阴影。

  • inset

默认阴影是外层的。指定inset表示内层阴影,即阴影落在元素盒模型的内部,效果通常就是内容被压低了【阴影位于边框内,背景之上,内容之下】。

  • <offset-x> <offset-y>

前两个长度值表示x、y轴的偏移量(垂直向下为y正方向)。

<offset-x>水平方向,正值表示阴影位于元素右边,负值表示阴影位于元素左边;<offset-y>垂直方向,正值表示阴影位于元素下方,负值表示阴影位于元素上方。

通常两者设置为0,通过 <blur-radius><spread-radius> 指定阴影平均地向四周显示。

  • <blur-radius>

第三个长度值,表示模糊半径,值越大,阴影越远处逐渐模糊变淡。默认值为0,没有模糊效果,阴影边缘锐利。通常不会使用默认值。

  • <spread-radius>

第四个长度值,表示阴影的范围或扩散范围。默认0,阴影与元素大小相同。赋值将会向内扩展。

  • <color> 阴影颜色

阴影效果

div {
    width: 150px;
    height: 150px;
    background-color: #fff;
    
    box-shadow: 120px 80px 40px 20px #0ff;
    /* 顺序为: offset-x, offset-y, blur-radius, spread-radius, color */
}

多重box-shadow叠加

通过对元素添加多个阴影,查看其叠加效果,已经对应的x、y方向。

<div class="shadows"></div>
.shadows{
    width: 130px;
    height: 50px;
    background-color: darkcyan;
    box-shadow: 5px 5px #6fff00,
                10px 10px #ff0000,
                15px 15px #000000;
}

其效果如下,在x、y正方向上扩展出的阴影,多个阴影叠加。

多个阴影,写在前面的权重大,阴影重合部分权重大的值在上面。

background-color:#fff;
box-shadow: blue 0px 0px 0px 2px inset, 
            rgba(255, 255, 255) 10px -10px 0px -3px, 
            rgb(31, 193, 27) 10px -10px,
            rgb(255, 255, 255) 20px -20px 0px -3px, 
            rgb(255, 217, 19) 20px -20px, 
            rgb(255, 255, 255) 30px -30px 0px -3px, 
            rgb(255, 156, 85) 30px -30px, 
            rgb(255, 255, 255) 40px -40px 0px -3px,
            rgb(255, 85, 85) 40px -40px;

box-shadow: rgb(85, 91, 255) 0px 0px 0px 3px, 
            rgb(31, 193, 27) 0px 0px 0px 6px, 
            rgb(255, 217,19) 0px 0px 0px 9px, 
            rgb(255, 156, 85) 0px 0px 0px 12px, 
            rgb(255, 85, 85) 0px 0px 0px 15px;

设置实现单边阴影

要想实现真正的单边阴影(防止其他边出现阴影),则<blur-radius> <spread-radius>模糊半径和扩展半径都应该为0,两个如果为正值,则会影响其他边也有阴影效果。

单边阴影效果:

.shadows-side{
    width: 120px;
    height: 120px;
    box-shadow: 5px 0px 0px 0px #87f;
}

不模糊和不扩展的情况下,四个单边的阴影互不影响

box-shadow: 10px 0px 0px 0px #87f,
            0px -10px 0px 0px rgb(52, 163, 18),
            -10px 0px 0px 0px rgb(233, 98, 15),
            0px 10px 0px 0px rgb(9, 186, 133);

如果要想使用模糊的单边,则会影响其他边也有阴影。一个相对较好的解决办法是指定扩展半径为适当的负值(即向内扩展)。

box-shadow: 15px 0px 10px -5px #87f,
            0px -15px 10px -5px rgb(52, 163, 18),
            -15px 0px 10px -5px rgb(233, 98, 15),
            0px 15px 10px -5px rgb(9, 186, 133);

关于阴影溢出

box-shadow会撑出原始box的宽高范围,如果父级加入了溢出隐藏overflow: hidden,将会导致阴影隐藏。

CSS box-shadow阴影示例参考 - Beautiful CSS box-shadow examples

参考