如何让Framer Motion的whileFocus在motion.div等元素点击时生效?
问题
我尝试使用Framer Motion的whileFocus属性,在元素获得焦点时改变其缩放比例。通过Tab键切换焦点时功能正常,但点击触发焦点仅在<motion.input/>元素上生效,<motion.div/>、<motion.button/>等元素无法通过点击触发whileFocus效果。示例组件如下:
const MyMotionComponent = () => { return ( <> {/*whileFocus works after clicking on this input element*/} <motion.input tabIndex={0} className="absolute cursor-pointer bg-blue-300" style={{ width: 100, height: 100, borderRadius: 50, x: 400, y: 200 }} whileFocus={{ scale: 2 }} /> {/*whileFocus does not work after clicking on this div element*/} <motion.div tabIndex={0} className="absolute cursor-pointer bg-amber-300" style={{ width: 100, height: 100, borderRadius: 50, x: 200, y: 200 }} whileFocus={{ scale: 2 }} /> </> ); };
请问如何让whileFocus在<motion.div/>这类支持子元素的元素上正常工作?
解决方案
核心原因
<div>这类非表单元素默认点击不会触发焦点,即便设置了tabIndex={0}让它能通过Tab键获取焦点,但浏览器不会在点击时自动给它赋予焦点;而<input>这类表单元素点击时,浏览器默认会主动设置焦点,因此whileFocus能正常生效。
解决方法
给<motion.div>添加点击事件,手动触发焦点:
import { useRef } from 'react'; import { motion } from 'framer-motion'; const MyMotionComponent = () => { const divRef = useRef(null); return ( <> <motion.input tabIndex={0} className="absolute cursor-pointer bg-blue-300" style={{ width: 100, height: 100, borderRadius: 50, x: 400, y: 200 }} whileFocus={{ scale: 2 }} /> <motion.div ref={divRef} tabIndex={0} className="absolute cursor-pointer bg-amber-300" style={{ width: 100, height: 100, borderRadius: 50, x: 200, y: 200 }} whileFocus={{ scale: 2 }} onClick={() => divRef.current?.focus()} /> </> ); };
补充说明
- 对于
<motion.button>,原生按钮本身点击会自动获取焦点,若出现不生效的情况,大概率是样式或其他代码干扰,同样可以用手动触发焦点的方式确保效果。 - 如果不需要浏览器默认的焦点边框,可以添加
outline: none样式,但要注意保留其他视觉反馈,保证页面的可访问性。
内容的提问来源于stack exchange,提问作者Isak Engström
相关产品推荐
相关产品推荐

