CSS :hover 无法获取鼠标进入方向,必须用 JavaScript 的 mouseenter 事件结合 getBoundingClientRect() 计算鼠标相对元素边界的偏移量来判断方向,并通过 CSS 自定义属性传递给样式系统实现方向感知动画。
纯 CSS 中的 :hover 只能识别“是否悬停”,并不会提供鼠标坐标或移动轨迹。因此,“用 hover 配合自定义变量”只能标记状态,无法据此推导方向。若要真正判断鼠标从上/下/左/右哪一侧进入,必须依靠 mouseenter 以及 mouseleave 事件,再结合元素边界计算。
核心方法是:当 mouseenter 触发后,先获取鼠标位置 event.clientX/Y,然后与目标元素的 getBoundingClientRect() 所返回的 top/right/bottom/left进行对比,即可判断鼠标从哪一边接近。
关键逻辑在于判断鼠标落点相对元素中心点所处的象限:
clientX - rect.left < rect.width / 2 → 更靠近左边clientY - rect.top < rect.height / 2 → 更靠近上边style.setProperty('--enter-dir', 'top')
之后便可以在 CSS 中通过 transition 或者 @keyframes 实现具有方向感知效果的动画。
立即学习“前端免费学习笔记(深入)”;
自定义属性需要设置在被 hover 的元素或其父级上,而且 JS 完成赋值后,只有等待样式重新计算才能生效。常见问题包括:
mouseenter 中立即读取 getComputedStyle(el).getPropertyValue('--enter-dir') 无法得到新值,因为它尚未进入渲染流程transition 若该变量为动画所依赖,还需让它的变化触发重绘,配合方式比如 transform 或者 opacity
var(--enter-dir) 来控制 content,因为 CSS 无法依据变量值切换字符串更稳妥的方式是由 JS 设置 --enter-dir: top 后,动画可由 class 切换或 CSS 属性选择器驱动,比如:
div[data-enter="top"]::before { transform: translateY(-20px);}
触摸设备既不会触发 mouseenter,touchstart ,也不具备坐标语义,强制适配很容易产生误判。实际项目更建议:
matchMedia('(hover: hover)') 为真时,才开启方向检测逻辑方向识别本身存在精度限制:当鼠标斜向快速掠过角落时,判断结果可能抖动。与仅比较中心点相比,加入 5–10px 的容差阈值会更稳定。