🔥一个有质感的拟态开关

前言

​ 最近在小红书冲浪的时候,看到一个拟态按钮的figma设计很有意思,效果如下

这种拟态风格,主要是通过修改内外阴影来实现的,考察box-shadown属性的时候到了

最终效果

这是实现的最终效果,除了背景动画有点生硬,大致效果是有了.

实现思路

整体设计
  • 分层容器 :使用三层嵌套结构(toggle__warpper > toggle > toggle__btn)构建立体感
  • 定位策略 :通过 position: absolute 实现按钮的精准定位滑动
  • 尺寸控制:固定尺寸容器(664px/184px)确保视觉稳定性
拟态视觉实现
  • 阴影体系(核心拟态效果):

    scss 复制代码
    box-shadow: 
      inset 0px 4px 13px 0 rgba(#000, 0.5), // 内凹阴影
      inset 0px -4px 13px 0 rgba(255, 255, 255, 1); // 高光提亮
  • 多层渐变背景

    scss 复制代码
    background: 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或者别的方式去实现.

总的来说效果还是有的.

相关推荐
majingming1231 小时前
FUNCTION
java·前端·javascript
A_nanda2 小时前
Vue项目升级
前端·vue3·vue2
SuperEugene2 小时前
Axios 接口请求规范实战:请求参数 / 响应处理 / 异常兜底,避坑中后台 API 调用混乱|API 与异步请求规范篇
开发语言·前端·javascript·vue.js·前端框架·axios
abigale033 小时前
【浏览器 API / 网络请求 / 文件处理】前端文件上传全流程:从基础上传到断点续传
前端·typescript·文件上传·vue cli
Setsuna_F_Seiei3 小时前
AI 对话应用之页面滚动交互的实现
前端·javascript·ai编程
新缸中之脑4 小时前
追踪来自Agent的Web 流量
前端
wefly20174 小时前
从使用到原理,深度解析m3u8live.cn—— 基于 HLS.js 的 M3U8 在线播放器实现
java·开发语言·前端·javascript·ecmascript·php·m3u8
英俊潇洒美少年5 小时前
vue如何实现react useDeferredvalue和useTransition的效果
前端·vue.js·react.js
kyriewen115 小时前
给浏览器画个圈:CSS contain 如何让页面从“卡成PPT”变“丝滑如德芙”
开发语言·前端·javascript·css·chrome·typescript·ecmascript
英俊潇洒美少年5 小时前
react19和vue3的优缺点 对比
前端·javascript·vue.js·react.js