请看这把小提琴:http://jsfiddle.net/ZWw3Z/5/

我的代码是:

p { position: relative; background-color: blue; } p:before { content: ''; position: absolute; left:100%; width: 10px; height: 100%; background-color: red; } <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate...</p>

我想只在伪元素(红色位)上触发一个单击事件。也就是说,我不希望在蓝色位上触发单击事件。


当前回答

这是由Fasoeu用最新的CSS3和JS ES6编辑的答案

编辑的演示没有使用JQuery。

最短的代码示例:

<p><span>Some text</span></p>
p {
    position: relative;
    pointer-events: none;
}
p::before {
    content: "";
    position: absolute;
    pointer-events: auto;
}
p span {
    display: contents;
    pointer-events: auto;
}
const all_p = Array.from(document.querySelectorAll('p'));

for (let p of all_p) {
    p.addEventListener("click", listener, false);
};

解释:

pointer-events control detection of events, removing receiving events from target, but keep receiving from pseudo-elements make possible to click on ::before and ::after and you will always know what you are clicking on pseudo-element, however if you still need to click, you put all content in nested element (span in example), but because we don't want to apply any additional styles, display: contents; become very handy solution and it supported by most browsers. pointer-events: none; as already mentioned in original post also widely supported.

JavaScript部分还使用了广泛支持的Array.from和for…的,但是在代码中不需要使用它们。

其他回答

这对我来说很管用:

$('#element').click(function (e) {
        if (e.offsetX > e.target.offsetLeft) {
            // click on element
        }
         else{
           // click on ::before element
       }
});

这是不可能的;伪元素根本不是DOM的一部分,所以你不能将任何事件直接绑定到它们,你只能绑定到它们的父元素。

如果你必须在红色区域上有一个点击处理程序,你必须创建一个子元素,比如span,把它放在<p>标签后面,将样式应用到p span而不是p:before,并绑定到它。

我将发布解决方案:

Offset()方法获取根元素的左上角信息。 getcomputedstyle()方法获取伪元素的样式。

请确保根元素的位置属性是相对的,而伪元素的位置属性是绝对的。 提琴演示在这里。 希望这能有所帮助。

额外的评论: 这个问题是11年前提出的,现在已经有了一个公认的答案。 我不顾上述事实发布这个解决方案的原因如下。

在伪元素上检测点击事件时,我也有同样的想法。 接受的答案(“添加子元素”)不能满足我的需求。 多亏了这个帖子,我有了解决方案的想法。 如果有人有类似的问题可以通过这篇文章来解决,我会很高兴。


/**
 * Click event listener.
 */
$(element).click((e) => {
    // mouse cursor position
    const mousePoint = { x: e.pageX, y: e.pageY };

    if (isMouseOnPseudoElement(mousePoint, e.target, 'before')) {
        console.log('[:before] pseudo-element was clicked');
    } else if (isMouseOnPseudoElement(mousePoint, e.target, 'after')) {
        console.log('[:after] pseudo-element was clicked');
    }
});

/**
 * Returns the info of whether the mouse cursor is over the pseudo-element.
 *
 * @param {JSON} point: coordinate of mouse cursor
 * @param {DOMElement} element: root element
 * @param {String} pseudoType: "before" or "after"
 * @returns {JSON}: info of whether the mouse cursor is over the pseudo-element
 */
function isMouseOnPseudoElement(point, element, pseudoType = 'before') {
    const pseudoRect = getPseudoElementRect(element, pseudoType);

    return point.y >= pseudoRect.top
        && point.y <= pseudoRect.bottom
        && point.x >= pseudoRect.left
        && point.x <= pseudoRect.right;
}

/**
 * Gets the rectangle info of the pseudo-element.
 *
 * @param {DOMElement} element: root element
 * @param {String} pseudoType: "before" or "after"
 * @returns {JSON}: rectangle info of the pseudo-element
 */
function getPseudoElementRect(element, pseudoType = 'before') {
    // top-left info of the root element
    const rootOffset = $(element).offset();

    // style of the pseudo-element
    const pseudoStyle = window.getComputedStyle(element, ':' + pseudoType);

    const top = rootOffset.top + parseFloat(pseudoStyle.top);
    const left = rootOffset.left + parseFloat(pseudoStyle.left);

    const height = parseFloat(pseudoStyle.height);
    const width = parseFloat(pseudoStyle.width);
    const borderTop = parseFloat(pseudoStyle['border-top-width']);
    const borderBottom = parseFloat(pseudoStyle['border-bottom-width']);
    const borderLeft = parseFloat(pseudoStyle['border-left-width']);
    const borderRight = parseFloat(pseudoStyle['border-right-width']);

    // rounds the decimal numbers detected when zooming
    return {
        top: Math.round(top),
        left: Math.round(left),
        bottom: Math.round(top + height + borderTop + borderBottom),
        right: Math.round(left + width + borderLeft + borderRight)
    };
}

在单击事件中添加条件以限制可单击区域。

    $('#thing').click(function(e) {
       if (e.clientX > $(this).offset().left + 90 &&
             e.clientY < $(this).offset().top + 10) {
                 // action when clicking on after-element
                 // your code here
       }
     });

DEMO

事实上,这是可能的。你可以检查被点击的位置是否在元素之外,因为这只会在::before或::after被点击时发生。

这个例子只检查右边的元素,但这在您的例子中是可行的。

span = document.querySelector('span'); 跨度。addEventListener('点击',函数(e) { if (e.offsetX > span.offsetWidth) { 跨度。className = 'c2'; }其他{ 跨度。className = 'c1'; } }); Div{边距:20px;} span:after{内容:' after ';位置:绝对的;} 跨度。C1{背景:黄色;} 跨度。C2:后面{背景:黄色;} < div > < span >元素< / span > < / div >

JSFiddle