请看这把小提琴: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>

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


当前回答

这些答案都不可靠,我的答案也不可靠得多。

除了注意事项外,如果您确实遇到了这样一种幸运的情况,即您试图单击的元素没有填充(这样元素的所有“内部”空间都被子元素完全覆盖),那么您可以根据容器本身检查click事件的目标。如果匹配,这意味着您单击了:before或:after元素。

显然,这两种类型(之前和之后)都不可行,但我已经实现了它作为一个hack/速度修复,它工作得很好,没有一堆位置检查,这可能是不准确的,取决于大约一百万个不同的因素。

其他回答

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

    $('#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

在现代浏览器中,您可以尝试使用css属性pointer-events(但这导致无法检测父节点上的鼠标事件):

p {
    position: relative;
    background-color: blue;
    color:#ffffff;
    padding:0px 10px;
    pointer-events:none;
}
p::before {
    content: attr(data-before);
    margin-left:-10px;
    margin-right:10px;
    position: relative;
    background-color: red;
    padding:0px 10px;
    pointer-events:auto;
}

当事件目标是“p”元素时,您就知道它是“p:before”。

如果仍然需要检测主p上的鼠标事件,可以考虑修改HTML结构。您可以添加span标签和以下样式:

p span {
    background:#393;
    padding:0px 10px;
    pointer-events:auto;
}

事件目标现在是“span”和“p:before”元素。

不使用jquery的示例:http://jsfiddle.net/2nsptvcu/

jquery示例:http://jsfiddle.net/0vygmnnb/

下面是支持指针事件的浏览器列表:http://caniuse.com/#feat=pointer-events

我将发布解决方案:

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)
    };
}

我的答案将适用于任何想要点击页面特定区域的人。这对我的绝对定位很有效:之后

多亏了这篇文章,我意识到(使用jQuery)我可以使用e.pageY和e.pageX,而不用担心浏览器之间的e.f offsety /X和e.c reenty /X问题。

Through my trial and error, I started to use the clientX and clientY mouse coordinates in the jQuery event object. These coordinates gave me the X and Y offset of the mouse relative to the top-left corner of the browser's view port. As I was reading the jQuery 1.4 Reference Guide by Karl Swedberg and Jonathan Chaffer, however, I saw that they often referred to the pageX and pageY coordinates. After checking the updated jQuery documentation, I saw that these were the coordinates standardized by jQuery; and, I saw that they gave me the X and Y offset of the mouse relative to the entire document (not just the view port).

我喜欢这个活动。pageY的想法,因为它总是相同的,因为它是相对于文档。我可以使用offset()将它与我的:after的父元素进行比较,它返回的X和Y也是相对于文档的。

因此,我可以在整个页面上提出一个永不改变的“可点击”区域范围。


这是我关于codeen的演示。


或者如果懒得用codeen,下面是JS:

我只关心例子中的Y值。

var box = $('.box');
// clickable range - never changes
var max = box.offset().top + box.outerHeight();
var min = max - 30; // 30 is the height of the :after

var checkRange = function(y) {
  return (y >= min && y <= max);
}

box.click(function(e){
  if ( checkRange(e.pageY) ) {
    // do click action
    box.toggleClass('toggle');
  }
});

这些答案都不可靠,我的答案也不可靠得多。

除了注意事项外,如果您确实遇到了这样一种幸运的情况,即您试图单击的元素没有填充(这样元素的所有“内部”空间都被子元素完全覆盖),那么您可以根据容器本身检查click事件的目标。如果匹配,这意味着您单击了:before或:after元素。

显然,这两种类型(之前和之后)都不可行,但我已经实现了它作为一个hack/速度修复,它工作得很好,没有一堆位置检查,这可能是不准确的,取决于大约一百万个不同的因素。