如何用一个<input>元素来写出开关的效果

这里的“开关”指的是移动端的开关。因为移动端我们要用手指来操作,而手指比鼠标的面积大得多,意味着点击的精确度会小得多,所以仍旧使用“复选框(<input type="checkbox">)”就不是很方便了,使用“开关”更方便——它看起来够大,容易操作,而且能从颜色来判断出状,容易观察。

移动端的开关大概长这样(图片来自网络)——

可以看到,开关有一个背景框和一个小圆点,不同状态下具有不同的颜色。

最近我在一门课上看到了用CSS3+<input>做出开关效果的方法,我在这里教给大家吧。

第一步,HTML结构。我这里说的是“用一个<input>标签”,但没那么简单哦。我们希望开关有且仅有两种状态,打开和关闭。<input>默认状态是普普通通的文字输入框,当然不行!那么,怎么样的<input>具有两种状态,还可以单独存在呢?答案已经呼之欲出了,就是我们的复选框(<input type = "checkbox"/>)。对,它是一个外表看似小孩,不,外表看似开关,实际上仍然是复选框的<input>。为了给它加上样式,我们给它加上class:

 <input class="bty-switch" type="checkbox" />

第二步,让复选框变得不再像它自己。复选框默认的样子还是跟开关相去甚远,而且它还是一个“替换元素”,改它的样式是很麻烦的,怎么办?有一个CSS属性可以去掉它原本的样子——-webkit-appearance,把它设为none即可。这之后,我们的复选框便可放飞自我,变成这样的圆框。我们还用-webkit-tap-highlight-color来去掉它被点击的效果

.bty-switch {
    /* 去掉checkbox的默认样式 */
    -webkit-appearance: none;
    /* 去掉checkbox默认的点击效果 */
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

第三步,绘制出圆框的模样。这一步就简单了,给圆框设置合适的宽和高,然后把边框圆角(border-radius)的大小设为高的一半即可(因为要画出胶囊形的效果)。记得设置默认边框色、背景色和选中后的边框色、背景色。我设置成了灰色和绿色。(开关开启的状态就用:checked来表示,也就是复选框的选中状态)

.bty-switch {
    box-sizing: content-box;
    /* 指定大小和圆角 */
    width: 2.6rem;
    height: 1.4rem;
    border: 1px solid #ccc;
    outline: 0;
    border-radius: .75rem;
    /* 默认的背景色是半透明黑色 */
    background-color: rgba(0, 0, 0, 0.1);
    /* 去掉checkbox的默认样式 */
    -webkit-appearance: none;
    /* 去掉checkbox默认的点击效果 */
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

/* 选中状态下的样式 */
.bty-switch:checked {
    border-color: #07C160;
    background-color: #07C160;
}

目前的效果是这样的:

第四步,画出白色的小圆点。这一步相当重要啦,我们的开关终于有了灵魂!看起来,小圆点是圆框的子元素,那么可能有朋友这时候就会问我了,input作为单标签,哪来的子元素?可以使用伪元素啊!

以下插播一小段伪元素的科普,是我个人经验的总结,有需要的同学可以看看——

伪元素可以用CSS来修饰,好像是一个“元素”,可它在HTML中不存在,所以并不能算是一个“真正的”元素,可以理解成“无中生有”吧。双标签基本上都可以使用伪元素,部分单标签不能使用,当然,复选框是可以用的。伪元素也不是想用几个就用几个,每个元素总共只能使用两个——::before和::after(::first-letter和::first-line也是伪元素,但是它们并不是“无中生有”的,显然无法用在这里),它们表现成子元素的样子,出现在元素内部,顾名思义,::before位于所有的子元素之前,::after位于所有的子元素之后。它们默认是行内元素,当然,加上绝对定位后就可以自由使用了。注意,想要使用伪元素,必须在伪元素选择器里加上content,里面的值是伪元素的文字或图片内容,就算没有内容也要写一个空字符串。它们可以用来做一些小装饰,这样可以少些几个元素,我有时候也会把::before用在固定的前缀上,比如“¥”)

好,言归正传。现在,我们用::after伪元素来做小圆点,给它设置合适的宽高注意,因为是圆点,所以宽高应该是相同的,并且正好等于<input>的高,然后加上border-radius:50%(小提示:border-radius:50%;会让正方形的元素变成正圆形,也会让长方形的元素变成椭圆形,不适合做胶囊形哦。)

/* 把checkbox当成容器来用,里面的圆点用伪元素来做 */
.bty-switch::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    /* 长宽与父级的宽相同,并指定圆角*/
    width: 1.4rem;
    height: 1.4rem;
    border-radius: .7rem;
    background-color: #fff;
    /* 阴影是用来划分边界的 */
    box-shadow: 0 0 2px #999;
}

这里用了box-shadow而不是border来表示小圆点的边框。我来解释一下。为了让小圆点看起来更清晰,与父容器有距离,是肯定要加边框的,但是用border的话会让小圆点的大小改变,更重要的是,我们加上去的边框圆角效果就不太好了,边框圆角永远是border-box这一层的圆角。box-shadow是不会撑大元素的,还会稍微有一些扩散的效果,比较好看。(前两个参数是x轴、y轴方向上的位移,这里写的是0,也就是阴影与小圆本身完全重合,然后加一点点的模糊,造成边框的效果,阴影颜色是灰色,与<input>背景色类似但不同)

开关打开和关闭的状态下,小圆点有什么不同呢?显然关闭的时候,小圆点靠左,打开的时候,小圆点靠右。所以我们可以来写一下,开关开启后,小圆点的样式。我们已经给小圆点设为绝对定位了,所以靠左就是left:0;那么靠右怎么办呢,right:0;吗?不对哦。

(这里另起一段吧,插播一小段关于绝对定位的科普,知识点来自于张鑫旭大大的《CSS世界》。如果position不为static,那么边偏移量top,right,bottom,left会生效。在绝对定位的模式中,它们可以分为两组,top与bottom一组,left与right一组假如元素没有设置宽高,那么当同组的两个属性都设置的时候,它们会同时生效,比如left:0;+ right:0; + bttom:0;可以做出类似底边框的效果,(我会用伪元素这么干来解决1像素边框问题)。假如元素的宽高被设置了,那么同组的两个属性只有一个会生效,top和left的优先级是更高的。如果在top/left生效后想要使用bottom/right来实现效果,那么只能把top/left设为auto才可以。

为了统一,即使是靠右,我们也使用left来实现。(等一下你就会知道为什么了)。因为我设置了<input>的宽度为2.6rem,高度为1,.4rem,所以小圆点宽度也是1.4rem,想让它靠右,那么left偏移量就得是input宽度与小圆点宽度之差,也就是1.2rem。

.bty-switch:checked:after {
    left: 1.2rem;
}

做到这一步后,效果如下,当当当当——

我们的开关已经有模有样了。

第五步,补充切换状态的过渡效果。如果说上一步是“画龙点睛”,那么这一步就是“锦上添花”了。从未选中到选中,<input>的背景色改变了,小圆点的位置也改变了,如果我们加一个过渡效果,那么看起来会显得更灵动,现在的效果太过生硬了。

要想加上过渡,我们就要使用CSS3属性transition,我一般是直接用这个简写的属性的。第一个参数是要过渡的CSS属性名称(不建议写all,这样没必要,太多的过渡也会影响性能),第二个参数是过渡的时长第三个参数是过渡的时间曲线函数(可以不写,默认ease),后面还有延时的参数,也可以不写;如果要对同一个元素的多个不同的属性加上不同时长和不同的时间曲线函数,使用逗号隔开。

(因为小圆点的位置靠左和靠右时我们都使用了left属性,所以给left属性加上过渡效果,就可以在切换状态的时候看到小圆点在缓缓滑动)

最后的代码是这样的:

/* 菜单里的开关,使用type为checkbox的input来做 */
.bty-switch {
    position: relative;
    box-sizing: content-box;
    /* 指定大小和圆角 */
    width: 2.6rem;
    height: 1.4rem;
    border: 1px solid #ccc;
    outline: 0;
    border-radius: .75rem;
    /* 默认的背景色是半透明黑色 */
    background-color: rgba(0, 0, 0, 0.1);
    /* 因为背景颜色和border在选中后发生了改变,所以就在这里加上过渡 */
    transition: background-color .3s, border .3s;
    /* 去掉checkbox的默认样式 */
    -webkit-appearance: none;
    /* 去掉checkbox默认的点击效果 */
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

/* 选中状态下的样式 */
.bty-switch:checked {
    border-color: #07C160;
    background-color: #07C160;
}

/* 把checkbox当成容器来用,里面的圆点用伪元素来做 */
.bty-switch::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    /* 长宽与父级的宽相同,并指定圆角*/
    width: 1.4rem;
    height: 1.4rem;
    border-radius: .7rem;
    background-color: #fff;
    /* 阴影是用来划分边界的 */
    box-shadow: 0 0 2px #999;
    /* 为了让开关有过渡效果,要使用transition属性。这个属性性能消耗大,要避免大规模使用 */
    transition: left 1s;
}

/* 选中状态下,圆点的左边缘位置等于父级宽度减去自己的宽度,这样就靠右了 */
.bty-switch:checked:after {
    left: 1.2rem;
}

恭喜你,大功告成啦,虽然比较简单,但至少也是一个看起来、点起来、用起来(可以根据checkbox是否选中来获取开关状态)效果都正常的开关啦。很高兴你读到了这里。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值