为什么CSS :focus伪类实现的按钮按压动画仅能生效一次?
问题根源
:focus伪类的触发逻辑和按压交互的需求不匹配:
:focus是元素获得焦点后的持续状态:第一次点击元素时,元素从非聚焦状态切换到聚焦状态,状态变更会触发一次动画;后续只要不点击其他区域让元素失焦,无论点击多少次元素,它的聚焦状态都不会发生变化,浏览器不会重复执行绑定的动画,这就是动画仅首次生效的核心原因。- 浏览器原生适配按压交互的瞬时状态伪类是
:active,每次元素被按下(鼠标按键未松开、触屏按压未抬起)时都会触发,不需要额外逻辑就能实现每次按压都播放动画的效果。
修正代码
只需要调整CSS的伪类绑定,补充平滑回弹的过渡即可,HTML结构无需改动:
.icon { text-decoration: none; display: flex; align-items: center; justify-content: center; height: 220px; width: 220px; margin: 15px 0px; background-color: #f2f3f7; box-shadow: 0.6rem 0.6rem 1.2rem #d2dce9, -0.5em -0.5em 1em #ffffff; border-radius: 3rem; overflow: hidden; /* 增加过渡实现松开按钮时的平滑回弹效果 */ transition: box-shadow 0.2s ease-in-out; } .icon img { width: 86%; height: 86%; border-radius: 50%; } /* 将原绑定在:focus上的动画移到:active伪类 */ .icon:active { animation: pressbtn 0.2s ease-in-out forwards; } @keyframes pressbtn { 0% { box-shadow: 0.6rem 0.6rem 1.2rem #d2dce9, -0.5em -0.5em 1em #ffffff; } 100% { box-shadow: inset 0.6rem 0.6rem 1.2rem #d2dce9, inset -0.5em -0.5em 1em #ffffff; } }
对应的HTML保持原有写法即可:
<a href="#" class="icon"> <img src="https://about.twitter.com/content/dam/about-twitter/en/brand-toolkit/brand-download-img-1.jpg.twimg.1920.jpg"> </a>
补充说明
- 原代码中动画结束状态设置为
box-shadow: none会导致按压后按钮阴影直接消失,不符合新拟态按钮的按压反馈逻辑,修正后的代码调整了动画结束状态为内凹阴影,匹配常规按压交互的视觉效果。 - 如果业务场景必须用
:focus触发动画,需要通过JS在每次点击时先移除动画属性、再重设动画属性,强制浏览器重启动画,但这种方案需要额外写脚本,性能和维护性都不如直接用:active实现按压反馈,非必要不推荐。
内容的提问来源于stack exchange,提问作者Maggie
相关产品推荐
相关产品推荐

