点击P标签外边距时如何返回对应P标签节点?
问题描述
现有如下代码,每个<p>标签通过margin属性分隔:
<div> <p> Lorem </p> <p> Lorem 2 </p> </div>
* { box-sizing: border-box; } div { height: 100px; border: 1px solid blue; } p { margin: 20px; border: 1px solid red; }
document.addEventListener("click", function(e) { console.log(e.target); });
当前点击<p>标签之间的margin区域时,事件返回的目标节点是<div>。要求在不允许将margin改为padding的情况下,实现点击<p>标签的外边距时返回对应的<p>标签节点。
解决方案
方法一:利用伪元素扩展<p>的可点击区域
由于margin区域不属于<p>的盒模型范围,点击时不会触发<p>的事件。我们可以给<p>添加伪元素,让伪元素覆盖其margin区域,这样点击margin区域时,事件会冒泡到对应的<p>元素。
修改后的CSS:
* { box-sizing: border-box; } div { height: 100px; border: 1px solid blue; position: relative; } p { margin: 20px; border: 1px solid red; position: relative; } /* 用伪元素覆盖p的margin区域 */ p::before { content: ''; position: absolute; top: -20px; left: -20px; right: -20px; bottom: -20px; pointer-events: auto; }
修改后的JavaScript:
document.addEventListener("click", function(e) { // 若点击的是伪元素,取其父元素p;否则直接取目标 const target = e.target.tagName === 'P' ? e.target : e.target.closest('p'); console.log(target); });
方法二:事件委托结合元素位置判断
如果无法修改CSS,可以通过JS计算每个<p>包含margin的完整布局范围,判断点击坐标落在哪个<p>的margin区域内,从而定位到对应的<p>元素。
修改后的JavaScript:
document.addEventListener("click", function(e) { const pElements = document.querySelectorAll('p'); let targetP = null; for (const p of pElements) { const rect = p.getBoundingClientRect(); const marginStyle = window.getComputedStyle(p); // 获取p的margin值 const marginTop = parseInt(marginStyle.marginTop); const marginBottom = parseInt(marginStyle.marginBottom); const marginLeft = parseInt(marginStyle.marginLeft); const marginRight = parseInt(marginStyle.marginRight); // 计算包含margin的完整区域范围 const fullRect = { top: rect.top - marginTop, bottom: rect.bottom + marginBottom, left: rect.left - marginLeft, right: rect.right + marginRight }; // 判断点击坐标是否在当前p的margin区域内 if (e.clientY >= fullRect.top && e.clientY <= fullRect.bottom && e.clientX >= fullRect.left && e.clientX <= fullRect.right) { targetP = p; break; } } console.log(targetP || e.target); });
内容的提问来源于stack exchange,提问作者Dom
相关产品推荐
相关产品推荐

