Only detect click event on pseudo-element
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.
Is it possible to detect a click of an :after or :before pseudo element with jQuery?
Maybe. Depending on how you structure your pseudo content you would have to rely on calculating mouse position for clicks on the actual div. The event handlers would all go on the div, and not the pseudo element because it doesn't exist in the DOM.
See Manipulating CSS :before and :after pseudo-elements using jQuery
for some more info. Especially BoltClock's answer.
Also see Felix's comment for another possible solution without mouse position: Only detect click event on pseudo-element
Use javascript to click on a pseudo-element?
A workaround for this would be to dynamically append a <span>
to the item and assigning a click method to it. Like this fiddle.
var item = $('<span />');
item.click(function() { alert('click'); });
$('div').append(item);
CSS
div { position:relative; background-color:#333;
padding:20px; margin:20px; float:left;
}
div span { content:""; display:block;
padding:5px; background-color:#f60; border:2px solid white;
position: absolute; top:-2px; right:-2px; border-bottom-left-radius: 10px;
}
Detect if element clicked is a pseudo element
Since you can't detect events on pseudo elements you can insert separate elements into the headerDiv
and check the target of the click event to accomplish the same objective. (Or only apply events to the new child elements)
Here I created two spans for "add notes" and "button" texts which get appended to the new div. A new css rule for the button span applies the margin and pointer cursor
window.addEventListener('load', () => {
// sticky profile notes
const notes = document.querySelector('#textarea-notes'); // Get textarea element
const headerDiv = document.createElement("div"); // Create a <div> element
headerDiv.id = 'div-header';
// Create two spans to insert in headerDiv
const notesTitle = document.createElement('span')
notesTitle.innerHTML = 'Add Notes'; // Insert instructions
// this span could also be a real <button>
const notesBtn = document.createElement('span');
notesBtn.textContent = 'button';
notesBtn.className = 'notes-btn'
headerDiv.append(notesTitle)
headerDiv.append(notesBtn)
// add header on top
notes.parentNode.insertBefore(headerDiv, notes);
// minimize sticky
headerDiv.addEventListener('click', e => {
let msg = 'Parent clicked';
if(e.target.matches('.notes-btn')){
msg = 'Button clicked';
}
console.log(msg)
});
});
#div-header {
padding: 10px;
cursor: move;
background-color: #ffffcc;
}
/*#div-header:after {
margin-left: 10px;
cursor: pointer;
content: 'button';
}*/
#div-header .notes-btn{
margin-left: 10px;
cursor: pointer;
}
#textarea-notes {
background-color: #ffffcc;
width: 100%;
}
<textarea id="textarea-notes">
</textarea>
How to detect if a psudo-element (::after) was clicked in React.js
I don't believe there's a way to distinguish click events from an element and it's pesduo element(s) - the same event handler will fire when the user clicks on either.
One thing you can do though is use CSS to disable pointer-events
on the host element, while allowing pointer-events
on the element's pseduo element(s). That would give you a "half-way-there" mechanism for detecting clicks on pseduo element(s) only:
div:after{
content:"X";
display:block;
pointer-events: initial;
}
div{
pointer-events:none;
}
With that, you would then use the regular onClick
handler which should now only fire when the ::after
element is clicked:
class PseudoExample extends Component{
render(){
return(
<div onClick={() => { console.log("after clicked"); }}>
I host a pseduo elements
</div>
)
}
}
Hope that helps!
clickable after pseudo element
UPDATE
I've had a little play and reckon I've come up with something that solves this issue for the original provided code.
Essentially I have assigned the same :after
CSS to a "dummy" class and then create and destroy an element with the dummy class on the fly. Between the create and destroy we are able to get the necessary dimensions (width, height, positioning). Finally we can compare these values to the click co-ordinates...
DEMO: http://jsfiddle.net/gvee/gNDCV/6/
CSS
#main {
background-color: red;
width: 100%;
height: 200px;
position: relative;
}
#main:after, .mainafter {
position: absolute;
bottom: -100px;
right: 50%;
background-color: blue;
width: 40%;
height: 20px;
content:" ";
}
JQuery
$('#main').click(function (e) {
var pseudoElement = $('<div></div>').addClass('mainafter');
$(this).append(pseudoElement);
var w = pseudoElement.width();
var h = pseudoElement.height();
var x = pseudoElement.position().left;
var y = pseudoElement.position().top;
pseudoElement.remove();
if (e.pageY - $(this).position().top > y &&
e.pageY - $(this).position().top < y + h &&
e.pageX - $(this).position().left > x &&
e.pageX - $(this).position().left < x + w
) {
alert('Not red');
}
});
If statement illustrated:
PageX
is the horizontal co-ordinate of the cursor.X
is the co-ordinate of the left-hand edge of the blue box.W
is the width of the blue box.
Therefore we can work out the right-hand edge of the blue box by simple addition: X+W
.
The same logic can be applied on the vertical co-ordinates (top=Y, bottom=Y+H).
The if
statement in our JQuery above checks if PageX
falls between the left and right-hand edges of the blue box and that PageY
is between the top and bottom.
i.e. is the cursor in the blue box!
There is a [kludgy] workaround to your provided code (where the :after
content is positioned below it's container)...
Work out the co-ordinate of the mouse click and see if that exceeds the height of the #main
div...
DEMO: http://jsfiddle.net/gvee/gNDCV/3/
CSS
#main {
background-color: red;
width: 100%;
height: 200px;
position: relative;
margin-bottom: 20px; /* to clear content:after */
}
#main:after {
position: absolute;
bottom: -20px; /* -(this.height) */
background-color: blue;
width: 20px;
height: 20px;
content:" ";
}
JQuery
$('#main').click(function (e) {
if (e.pageY - $(this).offset().top > $(this).height()) {
alert('Not red');
}
});
Firefox: Click on CSS pseudo element doesn't trigger click event
I think the easiest solution would be to extend the padding
to cover the pseudo-element.
.btn-close{
padding: 0 32px 0 0;
}
.btn-close:after {
right: 0;
}
Related Topics
Changing Element Style Attribute Dynamically Using JavaScript
Relative Paths in JavaScript in an External File
JavaScript Onclick Function Is Called Immediately (Not When Clicked)
How to Display an Image Stored as Byte Array in Html/JavaScript
Es6 Modules in the Browser: Uncaught Syntaxerror: Unexpected Token Import
Convert HTML to Data:Text/Html Link Using JavaScript
Referenceerror: $ Is Not Defined
Getting Value of HTML Checkbox from Onclick/Onchange Events
How to Re-Trigger a Webkit CSS Animation Via JavaScript
Is There a Dom Event That Fires When an HTML Select Element Is Closed
Difference Between the Different Methods of Putting JavaScript Code in an ≪A≫
Html Form Action and Onsubmit Issues
Convert Svg to Png With Applied Images as Background to Svg Elements
Upload Progress Indicators For Fetch
Script Tag Create With Innerhtml of a Div Doesn't Work
Drag Drop Files into Standard HTML File Input