点击div内input输入框时如何防止父级div元素失去焦点
点击div内input导致div焦点丢失的解决方法
问题复现
当给可聚焦的div(设置了tabIndex属性)内部放置input输入框时,点击input会让div失去焦点,绑定在div:focus状态上的样式直接失效,复现代码如下:
<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <style> .form:focus { outline: none; border:1px solid black; } .form:active { outline: none; border:1px solid black; } </style> <div class="form" style="padding:50px" tabIndex="1"> <input type="text" /> </div> </body> </html>
根本原因
浏览器遵循单焦点模型规则:同一时刻页面内仅能有一个元素持有焦点。点击内部input时,焦点会从外层div转移到input上,div本身不再处于聚焦状态,:focus伪类的样式自然不会生效。而:active伪类仅在鼠标按下的瞬间触发,松开后就会失效,无法维持持续的高亮样式。
最优解决方案
使用CSS原生的:focus-within伪类替代原有的:focus伪类。该伪类的匹配规则是:元素自身获得焦点,或元素内部任意后代元素获得焦点时,都会触发匹配,完全覆盖「点击外层div聚焦、点击内部input输入时外层div保持高亮」的需求。
修正后的代码:
<!DOCTYPE html> <html> <head> <title>Page Title</title> <style> .form:focus-within { outline: none; border:1px solid black; } </style> </head> <body> <div class="form" style="padding:50px" tabIndex="1"> <input type="text" /> </div> </body> </html>
兼容旧浏览器方案
如果需要兼容IE11等不支持:focus-within的老旧浏览器,可以通过少量JS实现同等效果:
- 把聚焦状态的样式绑定到自定义类上,比如
.form.focused - 监听内部input的
focus事件,触发时给外层div添加自定义类 - 监听内部input的
blur事件,触发时移除外层div的自定义类
示例代码:
.form.focused { outline: none; border:1px solid black; }
const formContainer = document.querySelector('.form'); const innerInput = formContainer.querySelector('input'); innerInput.addEventListener('focus', () => { formContainer.classList.add('focused'); }); innerInput.addEventListener('blur', () => { formContainer.classList.remove('focused'); });
内容的提问来源于stack exchange,提问作者lovida5233
相关产品推荐
相关产品推荐

