使用CSS var()实现的按钮动画仅首个元素生效如何解决
问题原因
document.querySelector('.btn')只会返回页面中第一个匹配.btn选择器的元素,你第二段脚本里定义的btn2实际选中的还是第一个按钮,第二个按钮根本没有绑定鼠标移动事件,无法更新--x/--y自定义属性,动画自然无法正常触发。- 逐按钮单独写绑定脚本的方式完全没有复用性,不可能适配动态生成的任意数量按钮。
可直接复用的修复代码
CSS部分(修正重复属性+补全默认值)
.btn { position: relative; /* 删除原代码重复的display声明 */ display: inline-flex; height: 50px; width: 100px; background: #fff; border: 2px solid rgb(11, 81, 211); border-radius: 10px; text-decoration: none; letter-spacing: 1px; overflow: hidden; align-items: center; justify-content: center; /* 给CSS变量加初始值,避免首次加载位置异常 */ --x: 50%; --y: 50%; } .btn span { padding: 10px 50%; position: relative; z-index: 1; font-size: 20px; color: rgb(11, 81, 211); /* 补文字颜色过渡,效果更顺滑 */ transition: color 0.3s; } .btn:hover span { color: #fff; } .btn::before { content: ''; position: absolute; top: var(--y); left: var(--x); transform: translate(-50%, -50%); width: 0; height: 0; border-radius: 50%; background: rgb(11, 81, 211); transition: width 0.5s, height 0.5s; } .btn:hover::before { width: 1200px; height: 1200px; }
HTML+JS部分(通用绑定,支持任意数量按钮含动态生成)
<div> <button type="submit" class="btn"><span>Plot</span></button> </div> <div> <button type="submit" class="btn"><span>Plot</span></button> </div> <script> // 全局事件委托,无需提前遍历按钮,后续动态新增的.btn按钮也能自动生效 document.addEventListener('mousemove', e => { const currentBtn = e.target.closest('.btn') if (!currentBtn) return const btnRect = currentBtn.getBoundingClientRect() // 计算鼠标相对于按钮左上角的坐标 const offsetX = e.clientX - btnRect.left const offsetY = e.clientY - btnRect.top currentBtn.style.setProperty('--x', `${offsetX}px`) currentBtn.style.setProperty('--y', `${offsetY}px`) }) </script>
关键优化点
- 用事件委托代替逐个绑定,代码量更小,自动适配所有现有和后续动态插入的
.btn元素 - 用
getBoundingClientRect()计算按钮位置,比原代码的offsetLeft/Top更可靠,不会受父级元素定位、滚动偏移影响 - 用
closest()匹配按钮元素,就算鼠标移到按钮内的span子元素上也能正确识别,不会出现事件触发断层 - 给CSS自定义属性设置了初始默认值,页面首次加载还没触发鼠标移动时,hover动画也不会出现位置跳变
内容的提问来源于stack exchange,提问作者Will Powell
相关产品推荐
相关产品推荐

