应统一用@mixin interact-state封装交互态,固化触发条件、持续时间和视觉幅度,禁用:hover防触摸残留,disabled改用aria-disabled配合微反馈。

怎么让按钮点击态在所有地方看起来一样
靠写死 :active 或 :hover 样式肯定不行——不同组件、不同嵌套层级下伪类触发时机和样式继承容易打架,尤其是带过渡动画时。Sass 的作用不是“多写几行变量”,而是把交互反馈的**触发条件、持续时间、视觉变化幅度**这三件事锁死在一个可复用的逻辑里。
实操建议:
- 用
@mixin interact-state封装常见交互态,参数只暴露$duration和$scale(比如按钮按压缩放)两个真正需要调节的值,其余如transform-origin、transition-property全部固化 - 所有按钮类(
.btn、.icon-btn、[role="button"])统一 include 这个 mixin,不单独写:active - 避免在 mixin 里写
color: $primary这类语义色——颜色应由组件自身决定,mixin 只管“动”和“停”的节奏
Sass变量命名怎么防冲突又不失语义
写 $btn-active-scale: 0.95 看似清楚,但一旦项目里出现卡片折叠、图标旋转等其他缩放需求,scale 就变成歧义词。真正该抽象的是“交互反馈强度”,而不是具体数值单位。
实操建议:
- 用
$interaction-tap-intensity: 0.95替代$btn-active-scale,强调这是“用户感知到的反馈程度”,不是 CSS 属性映射 - 所有交互相关变量加
interaction-前缀,和layout-、type-严格区隔 - 不定义
$interaction-duration-fast这种模糊值——直接用$interaction-duration-tap: 150ms,对应真实操作场景(tap / longpress / hover)
为什么:hover在触摸设备上会残留
这不是 Sass 能解决的问题,但用 Sass 统一管理样式时,很容易忽略这个兼容性雷区::hover 在 iOS Safari 上会延迟触发,且焦点离开后状态不自动清除,导致“假悬停”。单纯加 @media (hover: hover) 不够——很多安卓 WebView 根本不支持这个媒体查询。
实操建议:
- 交互 mixin 中默认禁用
:hover,只保留:active和focus-visible;真要加悬停反馈,用 JS 监听touchstart后临时加 class(如is-hovering) - 在
_variables.scss里设$interaction-enable-hover: false,作为全局开关,避免团队成员无意中开启 - 测试时必须在真机上验证:长按后快速移开手指,看是否残留高亮或缩放
如何让disabled状态也有一致的交互反馈
很多人以为 disabled 就是“不响应”,但用户点一个灰掉的按钮时,依然需要明确的视觉确认:“我点了,但它现在不能用”。CSS 的 :disabled 伪类本身不触发 :active,所以得绕开它。
实操建议:
- 不用原生
disabled属性,改用aria-disabled="true"+pointer-events: none,这样:active仍能被触发(虽然没效果),再配合 JS 拦截事件 - 为
[aria-disabled="true"]单独写一条transition: opacity 0.2s,点击瞬间给 0.1 秒淡出再恢复,模拟“被拒”的微反馈 - 禁止在 Sass 中对
disabled写transform: scale(1)这类重置——它会让用户误以为按钮“突然活了”
最麻烦的其实是设计系统里那些“半交互”状态:比如加载中按钮、权限不足按钮、网络断开时的提交按钮。它们的反馈节奏和普通 :active 不同,但又不能另起一套变量体系——这时候就得在 mixin 里加一个 $mode 参数,而不是多写三个 mixin。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











