前言
最近在小红书冲浪的时候,看到一个拟态按钮的figma
设计很有意思,效果如下
这种拟态风格,主要是通过修改内外阴影来实现的,考察
box-shadown
属性的时候到了
最终效果
这是实现的最终效果,除了背景动画有点生硬,大致效果是有了.
实现思路
整体设计
- 分层容器 :使用三层嵌套结构(
toggle__warpper
>toggle
>toggle__btn
)构建立体感 - 定位策略 :通过
position: absolute
实现按钮的精准定位滑动 - 尺寸控制:固定尺寸容器(664px/184px)确保视觉稳定性
拟态视觉实现
-
阴影体系(核心拟态效果):
scssbox-shadow: inset 0px 4px 13px 0 rgba(#000, 0.5), // 内凹阴影 inset 0px -4px 13px 0 rgba(255, 255, 255, 1); // 高光提亮
-
多层渐变背景:
scssbackground: linear-gradient(#fff, #828a9a); // 容器基础渐变 background: linear-gradient(170deg, #ffffff, #f4f7fd 20%, #afb5c1, #929caf); // 按钮复杂渐变
-
伪元素投影:
scss&::after { background: rgba(#192d55, 0.19); filter: blur(16px); // 模糊投影增强立体感 }
交互逻辑实现
vue
<script setup>
import { ref } from 'vue'
const toggleStatus = ref(false)
const toggleBtn = ref(null)
const onToggleClick = () => {
const btnDom = toggleBtn.value
btnDom.style.left = toggleStatus.value ? '-12px' : '346px'
toggleStatus.value = !toggleStatus.value
}
</script>
完整代码
vue
<template>
<main class="container">
<div class="toggle__warpper">
<div
class="toggle"
:class="{
'toggle--active': toggleStatus
}"
@click="onToggleClick"
>
<div class="toggle__btn" ref="toggleBtn">
<div class="toggle__btn--after"></div>
<div class="toggle__btn--before"></div>
</div>
</div>
</div>
</main>
</template>
<script setup>
import { ref } from 'vue'
const toggleStatus = ref(false)
const toggleBtn = ref(null)
const onToggleClick = () => {
const btnDom = toggleBtn.value
btnDom.style.left = toggleStatus.value ? '-12px' : '346px'
toggleStatus.value = !toggleStatus.value
}
</script>
<style lang="scss" scoped>
.container {
background: linear-gradient(#fff, #a7adbb);
}
.toggle {
position: relative;
width: 600px;
height: 120px;
border-radius: 64px;
background: linear-gradient(#fff, #828a9a);
box-shadow:
inset 0px 4px 13px 0 rgba(#000, 0.5),
inset 0px -4px 13px 0 rgba(255, 255, 255, 1);
display: flex;
align-items: center;
&--active {
animation: bgAnimation 0.35s linear 0.35s forwards;
}
&__warpper {
border-radius: 120px;
width: 664px;
height: 184px;
box-shadow:
inset 0px 4px 13px 0 rgba(25, 45, 85, 0.5),
inset 0px -4px 13px 0 rgba(255, 255, 255, 1);
display: flex;
align-items: center;
justify-content: center;
}
&__btn {
position: absolute;
border-radius: 120px;
left: -12px;
width: 268px;
height: 160px;
background: linear-gradient(170deg, #ffffff, #f4f7fd 20%, #afb5c1, #929caf);
padding: 24px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
cursor: pointer;
box-shadow: 14px 33px 20px -15px rgba(25, 45, 85, 0.45);
transition: all ease-in-out 0.35s;
&--after {
width: 100px;
height: 115px;
background: linear-gradient(101deg, #cfd5dd, #f9f9f9);
border-radius: 50%;
}
&--before {
width: 100px;
height: 115px;
background: linear-gradient(112deg, #969fb0, #ffffff);
border-radius: 50%;
}
&::after {
position: absolute;
content: '';
left: 53px;
bottom: -58px;
width: 250px;
height: 174px;
background: rgba(#192d55, 0.19);
border-radius: 120px;
filter: blur(16px);
z-index: 999;
display: block;
}
}
}
// 背景渐变动画
@keyframes bgAnimation {
0% {
background: linear-gradient(#fff, #828a9a);
}
100% {
background: linear-gradient(#9cff8c, #0b4f00);
}
}
</style>
遇到的问题
我想要弄一个让这个开关切换状态的时候,这个背景变化应该是要有一点过渡的,但是用css
的动画去实现,发现背景的变化永远都是瞬间的,没有过渡效果,如果想要背景也有渐变就需要用js
或者别的方式去实现.
总的来说效果还是有的.