可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
My code is:
p {
position: relative;
background-color: blue;
}
p:before {
content: \'\';
position: absolute;
left:100%;
width: 10px;
height: 100%;
background-color: red;
}
Please see this fiddle: http://jsfiddle.net/ZWw3Z/5/
I would like to trigger a click event only on the pseudo-element (the red bit). That is, I don\'t want the click event to be triggered on the blue bit.
回答1:
This is not possible; pseudo-elements are not part of the DOM at all so you can\'t bind any events directly to them, you can only bind to their parent elements.
If you must have a click handler on the red region only, you have to make a child element, like a span
, place it right after the opening <p>
tag, apply styles to p span
instead of p:before
, and bind to it.
回答2:
Actually, it is possible. You can check if the clicked position was outside of the element, since this will only happen if ::before
or ::after
was clicked.
This example only checks the element to the right but that should work in your case.
span = document.querySelector(\'span\');
span.addEventListener(\'click\', function (e) {
if (e.offsetX > span.offsetWidth) {
span.className = \'c2\';
} else {
span.className = \'c1\';
}
});
div { margin: 20px; }
span:after { content: \'AFTER\'; position: absolute; }
span.c1 { background: yellow; }
span.c2:after { background: yellow; }
<div><span>ELEMENT</span></div>
JSFiddle
回答3:
On modern browsers you can try with the pointer-events css property (but it leads to the impossibility to detect mouse events on the parent node):
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;
}
When the event target is your \"p\" element, you know it is your \"p:before\".
If you still need to detect mouse events on the main p, you may consider the possibility to modify your HTML structure. You can add a span tag and the following style:
p span {
background:#393;
padding:0px 10px;
pointer-events:auto;
}
The event targets are now both the \"span\" and the \"p:before\" elements.
Example without jquery: http://jsfiddle.net/2nsptvcu/
Example with jquery: http://jsfiddle.net/0vygmnnb/
Here is the list of browsers supporting pointer-events: http://caniuse.com/#feat=pointer-events
回答4:
My answer will work for anyone wanting to click a definitive area of the page. This worked for me on my absolutely-positioned :after
Thanks to this article, I realized (with jQuery) I can use e.pageY
and e.pageX
instead of worrying about e.offsetY/X
and e.clientY/X
issue between browsers.
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).
I liked this event.pageY
idea because it would always be the same, as it was relative to the document. I can compare it to my :after\'s parent element using offset(), which returns its X and Y also relative to the document.
Therefore, I can come up with a range of \"clickable\" region on the entire page that never changes.
Here\'s my demo on codepen.
or if too lazy for codepen, here\'s the JS:
* I only cared about the Y values for my example.
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\');
}
});
回答5:
This works for me:
$(\'#element\').click(function (e) {
if (e.offsetX > e.target.offsetLeft) {
// click on element
}
else{
// click on ::before element
}
});
回答6:
Short Answer:
I did it.
I even did it in pure javascript and wrote a function for dynamic usage for all the little people out there...
Working example with function that you can steal
Long Answer:
...Still did it.
It took me awhile to do it, since a psuedo element is not really on the page. While some of the answers above work in SOME scenarios, they ALL fail to be both dynamic and work in a scenario in which an element is both unexpected in size and position(such as absolute positioned elements overlaying a portion of the parent element). Mine does not.
Usage:
//some element selector and a click event...plain js works here too
$(\"div\").click(function() {
//returns an object {before: true/false, after: true/false}
psuedoClick(this);
//returns true/false
psuedoClick(this).before;
//returns true/false
psuedoClick(this).after;
});
How it works:
It grabs the height, width, top, and left positions(based on the position away from the edge of the window) of the parent element and grabs the height, width, top, and left positions(based on the edge of the parent container) and compares those values to determine where the psuedo element is on the screen.
It then compares where the mouse is. As long as the mouse is in the newly created variable range then it returns true.
Note:
It is wise to make the parent element RELATIVE positioned. If you have an absolute positioned psuedo element, this function will only work if it is positioned based on the parent\'s dimensions(so the parent has to be relative...maybe sticky or fixed would work too....I dont know).
Code:
function psuedoClick(parentElem) {
var beforeClicked,
afterClicked;
var parentLeft = parseInt(parentElem.getBoundingClientRect().left, 10),
parentTop = parseInt(parentElem.getBoundingClientRect().top, 10);
var parentWidth = parseInt(window.getComputedStyle(parentElem).width, 10),
parentHeight = parseInt(window.getComputedStyle(parentElem).height, 10);
var before = window.getComputedStyle(parentElem, \':before\');
var beforeStart = parentLeft + (parseInt(before.getPropertyValue(\"left\"), 10)),
beforeEnd = beforeStart + parseInt(before.width, 10);
var beforeYStart = parentTop + (parseInt(before.getPropertyValue(\"top\"), 10)),
beforeYEnd = beforeYStart + parseInt(before.height, 10);
var after = window.getComputedStyle(parentElem, \':after\');
var afterStart = parentLeft + (parseInt(after.getPropertyValue(\"left\"), 10)),
afterEnd = afterStart + parseInt(after.width, 10);
var afterYStart = parentTop + (parseInt(after.getPropertyValue(\"top\"), 10)),
afterYEnd = afterYStart + parseInt(after.height, 10);
var mouseX = event.clientX,
mouseY = event.clientY;
beforeClicked = (mouseX >= beforeStart && mouseX <= beforeEnd && mouseY >= beforeYStart && mouseY <= beforeYEnd ? true : false);
afterClicked = (mouseX >= afterStart && mouseX <= afterEnd && mouseY >= afterYStart && mouseY <= afterYEnd ? true : false);
return {
\"before\" : beforeClicked,
\"after\" : afterClicked
};
}
Support:
I dont know....it looks like ie is dumb and likes to return auto as a computed value sometimes. IT SEEMS TO WORK WELL IN ALL BROWSERS IF DIMENSIONS ARE SET IN CSS. So...set your height and width on your psuedo elements and only move them with top and left. I recommend using it on things that you are okay with it not working on. Like an animation or something. Chrome works...as usual.
回答7:
Add condition in Click event to restrict the clickable area .
$(\'#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
回答8:
None of these answers are reliable, and mine wont be much more reliable.
Caveats aside, if you do get into the lucky scenario where the element you\'re trying to have clicked doesn\'t have padding (such that all of the \"inner\" space of the element is completely covered by sub-elements), then you can check the target of the click event against the container itself. If it matches, that means you\'ve clicked a :before or :after element.
Obviously this would not be feasible with both types (before and after) however I have implemented it as a hack/speed fix and it is working very well, without a bunch of position checking, which may be inaccurate depending on about a million different factors.
回答9:
No,but you can do like this
In html file add this section
<div class=\"arrow\">
</div>
In css you can do like this
p div.arrow {
content: \'\';
position: absolute;
left:100%;
width: 10px;
height: 100%;
background-color: red;
}
Hope it will help you