css实现开关组件效果,滑块组件效果。自己实现小程序滑块开关组件 电脑版发表于:2024/6/5 11:49 [TOC] ### 效果如下 ![](https://img.tnblog.net/arcimg/aojiancc2/21162ca85a014f8a8302f530eab72a90.png) ![](https://img.tnblog.net/arcimg/aojiancc2/676a2707cf4e4a559f6f1a820969f542.png) 切换的时候会有动态的效果 ### 代码如下,纯HTML+CSS 样式里边的注释都写得比较清晰了,需要自定义效果,圆角什么的自行修改即可 ``` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .switch { position: relative; display: inline-block; width: 108px; height: 34px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; /* background: #F1F4F5; */ background: #eee; border-radius: 8rpx 8rpx 8rpx 8rpx; -webkit-transition: .4s; transition: .4s; } .slider:before { position: absolute; content: ""; /* content: "未读"; */ height: 26px; width: 46px; left: 4px; text-align: center; line-height: 26px; /* color: #5EC6A7; */ bottom: 4px; background-color: white; border-radius: 8rpx 8rpx 8rpx 8rpx; -webkit-transition: .4s; transition: .4s; } /* 如果选中的状态下有背景颜色,边框,阴影这些变化可以使用下面的样式 */ /* input:checked+.slider { background-color: #2196F3; } input:focus+.slider { box-shadow: 0 0 1px #2196F3; } */ /* 动画切换效果,就是那个伪类块块的滑动动画 input:checked 的意思是当input标签选中的时候,具体用的时候可以多加一点限制, 或者直接用一个具体的样式限制,比如可以修改为.switch_input:checked+.slider:before +.slider 的意思就是选中input标签的相邻的兄弟节点 .slider:before 这里就是样式slider后面的伪类选择器 */ input:checked+.slider:before { -webkit-transform: translateX(53px); -ms-transform: translateX(53px); transform: translateX(53px); } /* 选中状态下 左边的文字位置与样式 这里样式的意思就是input选中的时候找到它相邻的兄弟节点slider,然后找到slider的后代元素lefTag */ input:checked+.slider .lefTag { color: #313960; } /* 选中状态下 右边的文字位置与样式 */ input:checked+.slider .rightTag { color: #5EC6A7; } /* 默认状态下左边的文字位置与样式 */ .lefTag { position: absolute; left: 12px; top: 7px; font-size: 15px; color: #5EC6A7; } /* 默认状态下右边的文字位置与样式 */ .rightTag { position: absolute; right: 13px; top: 7px; font-size: 15px; color: #313960; } </style> </head> <body> <label class="switch"> <input type="checkbox" class="switch_input" hidden> <div class="slider round"> <div class="lefTag">未读</div> <div class="rightTag">全部</div> </div> </label> </body> </html> ``` ### 用于uni-app开发编译到微信小程序开发工具运行的 用于uni-app开发使用`npm run dev:mp-weixin`编译到微信小程序开发工具运行调试的,开发工具是用的是vscode #### 效果图如下: ![](https://img.tnblog.net/arcimg/aojiancc2/a9e2e8fe551e4373b86500c7c9707ded.png) 如果直接把上面的代码和样式用于小程序中是运行不起的,`input type="checkbox"`这个在微信小程序中没有效果的,所以改变了一下实现思路,直接都用view来实现,然后是否选中的状态用点击事件和vue的数据绑定来实现,还有一点就是那个移动滑块的实现从伪类换成了view。 #### 代码如下,样式像素单位是px版本 具体关键代码的实现注释即可 ``` <template> <view class="message-container"> <view class="titleWrap"> <view class="title">{{ state.title }}</view> <view> <view class="switch" @tap="swichChoise"> <view class="switch_input" hidden /> <!-- 这里当属性state.isChoise为true的时候就会多一个选中状态下的样式sliderRun --> <view class="slider round" :class="{ sliderRun: state.isChoise }"> <view class="lefTag">未读</view> <view class="rightTag">全部</view> <view class="swtichTag"></view> </view> </view> </view> </view> <view class="splitline"></view> </view> </template> <script setup lang="ts" name="tasks"> import { defineAsyncComponent, reactive, onMounted, toRefs, ref } from 'vue'; const state = reactive({ title: '消息通知', isChoise: false, }) onMounted(() => { }) // 切换选中状态 const swichChoise = () => { state.isChoise = !state.isChoise } </script> <style scoped="scoped" lang="scss"> .message-container { padding: 15px; .titleWrap { display: flex; justify-content: space-between; align-items: center; .title { font-family: PingFang SC, PingFang SC; font-weight: 400; font-size: 30rpx; color: #313960; } } .splitline { margin-left: -20rpx; margin-right: -20rpx; margin-top: 30rpx; height: 1rpx; background: #f3f3f3; } } </style> <!-- 滑块开关按钮的样式 --> <style scoped="scoped" lang="scss"> .switch { position: relative; display: inline-block; width: 108px; height: 34px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #F1F4F5; border-radius: 8rpx 8rpx 8rpx 8rpx; -webkit-transition: .4s; transition: .4s; } .swtichTag { position: absolute; height: 26px; width: 46px; left: 4px; text-align: center; line-height: 26px; bottom: 4px; background-color: white; border-radius: 8rpx 8rpx 8rpx 8rpx; -webkit-transition: .4s; transition: .4s; } .sliderRun { // 选中状态下滑块往右边移动 .swtichTag { -webkit-transform: translateX(53px); -ms-transform: translateX(53px); transform: translateX(53px); } /* 选中状态下 左边的文字位置与样式 */ .lefTag { color: #313960; } /* 选中状态下 右边的文字位置与样式 */ .rightTag { color: #5EC6A7; } } /* 默认状态下左边的文字位置与样式 */ .lefTag { position: absolute; left: 12px; top: 7px; font-size: 15px; color: #5EC6A7; z-index: 999; } /* 默认状态下右边的文字位置与样式 */ .rightTag { position: absolute; right: 13px; top: 7px; font-size: 15px; color: #313960; z-index: 999; } </style> ``` #### 样式像素单位是rpx版本 如果是运行到微信小程序的,最好像素单位还是使用rpx ``` <template> <view class="message-container"> <view class="titleWrap"> <view class="title">{{ state.title }}</view> <view> <view class="switch" @tap="swichChoise"> <view class="switch_input" hidden /> <!-- 这里当属性state.isChoise为true的时候就会多一个选中状态下的样式sliderRun --> <view class="slider round" :class="{ sliderRun: state.isChoise }"> <view class="lefTag">未读</view> <view class="rightTag">全部</view> <view class="swtichTag"></view> </view> </view> </view> </view> <view class="splitline"></view> </view> </template> <script setup lang="ts" name="tasks"> import { defineAsyncComponent, reactive, onMounted, toRefs, ref } from 'vue'; const state = reactive({ title: '消息通知', isChoise: false, }) onMounted(() => { }) // 切换选中状态 const swichChoise = () => { state.isChoise = !state.isChoise } </script> <style scoped="scoped" lang="scss"> .message-container { padding: 30rpx 20rpx 10rpx 20rpx; .titleWrap { display: flex; justify-content: space-between; align-items: center; .title { font-family: PingFang SC, PingFang SC; font-weight: 400; font-size: 30rpx; color: #313960; } } .splitline { margin-left: -20rpx; margin-right: -20rpx; margin-top: 30rpx; height: 1rpx; background: #f3f3f3; } } </style> <!-- 滑块开关按钮的样式 --> <style scoped="scoped" lang="scss"> .switch { position: relative; display: inline-block; width: 216rpx; height: 68rpx; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #F1F4F5; border-radius: 8rpx 8rpx 8rpx 8rpx; -webkit-transition: .4s; transition: .4s; } .swtichTag { position: absolute; height: 52rpx; width: 92rpx; left: 8rpx; text-align: center; line-height: 52rpx; bottom: 8rpx; background-color: white; border-radius: 8rpx 8rpx 8rpx 8rpx; -webkit-transition: .4s; transition: .4s; } .sliderRun { // 选中状态下滑块往右边移动 .swtichTag { -webkit-transform: translateX(108rpx); -ms-transform: translateX(108rpx); transform: translateX(108rpx); } /* 选中状态下 左边的文字位置与样式 */ .lefTag { color: #313960; } /* 选中状态下 右边的文字位置与样式 */ .rightTag { color: #5EC6A7; } } /* 默认状态下左边的文字位置与样式 */ .lefTag { position: absolute; left: 24rpx; top: 12rpx; font-size: 30rpx; color: #5EC6A7; z-index: 999; } /* 默认状态下右边的文字位置与样式 */ .rightTag { position: absolute; right: 26rpx; top: 12rpx; font-size: 30rpx; color: #313960; z-index: 999; } </style> ```