CSS实现点击按钮仅内部宽度变化 外层宽度与阴影异常问题
按钮按下交互阴影异常修复
问题说明
- 预期效果:用户按下按钮时,仅按钮内部容器宽度发生变化,外层整体容器(黑色背景区域)宽度保持固定
- 现存问题:点击按钮时,按钮阴影出现不符合预期的异常变动

原有实现代码
HTML 部分
<button class="btn btn__primary" type="button"> Continue <i class="fa-solid fa-sparkles m-l-8px"></i> </button>
SCSS 部分
.btn { display: flex; flex-direction: row; justify-content: center; align-items: center; padding: 12px; font-family: $aeonik_bold; font-size: 15px; line-height: 100%; letter-spacing: 0.55px; border: 1.5px solid $button_border_color; box-sizing: border-box; border-radius: 4px; box-shadow: -1px 1px 0px 1.5px $button_border_color; text-decoration: none; transition: all 0.3s; animation-timing-function: ease-in-out; animation-duration: 150ms; cursor: pointer; width: 100%; &:active { box-shadow: none; background-color: #5a44ff; animation-timing-function: ease-in-out; animation-duration: 150ms; } &:focus { box-shadow: none; background-color: #5a44ff; animation-timing-function: ease-in-out; animation-duration: 150ms; } &:disabled { background: #d9dbe9; border: 1.5px solid #d9dbe9; box-sizing: border-box; border-radius: 4px; cursor: default; } &__primary { background-color: $purple_resting; color: white; animation-timing-function: ease-in-out; animation-duration: 150ms; &:not(:disabled) { &:hover { background-color: #6955ff; border: 1.5px solid #170f49; box-sizing: border-box; border-radius: 4px; box-shadow: -0.5px 0.5px 0px 1px $button_border_color; animation-timing-function: ease-in-out; animation-duration: 150ms; } } } }
问题原因
- 代码中使用了
transition: all 0.3s,会给所有可动画属性加上过渡效果,阴影属性也被包含在内 - hover、active、focus状态下反复修改box-shadow、border的参数,甚至直接将阴影设为none,不同状态下阴影的偏移量、扩展半径参数不统一,最终导致阴影出现跳变动效
- 直接修改按钮本身的阴影、边框属性,会改变按钮的视觉占位,和“外层容器固定不动”的需求冲突
修复方案
核心修改逻辑:外层按钮的阴影、边框、整体尺寸全程固定,仅调整内部视觉属性实现按下效果,过渡效果只绑定需要变化的属性。
修正后的SCSS核心代码:
.btn { display: flex; flex-direction: row; justify-content: center; align-items: center; padding: 12px; font-family: $aeonik_bold; font-size: 15px; line-height: 100%; letter-spacing: 0.55px; // 边框、阴影固定,所有交互状态下不修改 border: 1.5px solid $button_border_color; box-sizing: border-box; border-radius: 4px; box-shadow: -1px 1px 0px 1.5px $button_border_color; text-decoration: none; // 替换原有的transition: all,只过渡需要变化的属性,排除阴影、边框 transition: background-color 0.15s ease-in-out, padding 0.15s ease-in-out; cursor: pointer; width: 100%; &:active { // 删除原有的box-shadow: none,保持阴影不变 background-color: #5a44ff; // 微调上下内边距模拟按下位移效果,不改变外层整体尺寸 padding: 13px 12px 11px 12px; } &:focus { // 删除原有的box-shadow: none,保持阴影不变 background-color: #5a44ff; padding: 13px 12px 11px 12px; } &:disabled { background: #d9dbe9; border: 1.5px solid #d9dbe9; box-shadow: none; box-sizing: border-box; border-radius: 4px; cursor: default; } &__primary { background-color: $purple_resting; color: white; &:not(:disabled) { &:hover { background-color: #6955ff; // 删除hover状态下修改border、box-shadow的代码,保持外层样式固定 } } } }
修复后效果:
- 外层按钮的阴影、边框、整体宽度完全固定,不会出现阴影异常跳动的问题
- 按下时仅通过内边距微调实现内部视觉位移,符合“内部动、外层不动”的需求
- 仅对必要属性做过渡,动效更流畅,性能更好
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

