Hovering over pseudo after element to change the style

Tags:



I’m trying to create a simple demo where rolling over a pseudo element will change the style of its parent. In other words, I want to be able to roll over the letter e in the top right corner of the image and then display the text content.

I’ve managed to get it working when rolling over the image itself, but not the pseudo element. I’ve commented out the working code for rolling over the image itself, and left the incorrect pseudo rollover code uncommented out.

I wonder whether you can actually select pseudo elements in JS as it shows null when trying to select any pseudo element.

Any ideas would be appreciated. Thanks for any help. The code is below:

Codepen: https://codepen.io/anon/pen/NZvdzr

/*document.querySelector('#img-wrap').onmouseover = function() {
  document.querySelector('#caption-wrap').style.opacity = 1;
}
document.querySelector('#img-wrap').onmouseout = function() {
  document.querySelector('#caption-wrap').style.opacity = 0;
}*/

document.querySelector('#img-wrap:after').onmouseover = function() {
  document.querySelector('#caption-wrap').style.opacity = 1;
}
document.querySelector('#img-wrap:after').onmouseout = function() {
  document.querySelector('#caption-wrap').style.opacity = 0;
}
#img-wrap {
  width: 30%;
  position: relative;
}
#caption-wrap {
  position: absolute;
  top: 0;
  right: 0;
  opacity: 0;
}
img {
  width: 100%;
}
#img-wrap:after {
  content: 'e';
  position: absolute;
    top: 0;
  right: 0;
}
<div id='img-wrap'>
  <img src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-bCnPPMYp6QIfrCr2BR-imm_Sw9IHCXIXzE5fei7R8PTBKYGd'>
  <div id='caption-wrap'>
    <p>some text will appear</p>
  </div>
</div>

Answer

You cannot listen to pseudo elements, but you can find out some interesting info via window.getComputedStyle(). Below is a demo.

I’m listening to mouse move on the image element and comparing the coords to see if they fall between the rectangle of the pseudo element.

There is a padding of 2px on each tolerance, you could change that to something else if you want to be more forgiving with the mouse over detection.

CanIUse.com says window.getComputedStyle() is supported by all browsers, but I haven’t tested if they all return the proper coordinate information for this to work – you should cross browser test this before using.

var element = document.querySelector('#img-wrap') 

element.onmousemove = function(event){
  var elementRect = element.getBoundingClientRect()
  var pseudo = window.getComputedStyle(element, ':after')
  var pseudoRect = { 
    top: parseFloat(pseudo.top), 
    left: parseFloat(pseudo.left), 
    width: parseFloat(pseudo.width),
    height: parseFloat(pseudo.height),
  }    
  var mouseX = event.clientX
  var mouseY = event.clientY
  var yTolTop = elementRect.top + pseudoRect.top - 2
  var yTolBot = elementRect.top + pseudoRect.top + pseudoRect.height + 2
  var xTolLeft = elementRect.left + pseudoRect.left - 2
  var xTolRight = elementRect.left + pseudoRect.left +  pseudoRect.width + 2
  //console.log(elementRect.top, yTolTop, mouseY, yTolBot, " | ", elementRect.left, xTolLeft, mouseX, xTolRight)
  if(mouseY > yTolTop  && mouseY < yTolBot && mouseX > xTolLeft  && mouseX < xTolRight){
    document.querySelector('#caption-wrap').style.opacity = 1;
  }else{
    document.querySelector('#caption-wrap').style.opacity = 0;
  }
}

element.onmouseout = function(){
  document.querySelector('#caption-wrap').style.opacity = 0;
}
#img-wrap {
  width: 30%;
  position: relative;
}
#caption-wrap {
  position: absolute;
  top: 0;
  right: 0;
  opacity: 0;
}
img {
  width: 100%;
}
#img-wrap:after {
  content: 'e';
  position: absolute;
    top: 0;
  right: 0;
}
<div id='img-wrap'>
  <img src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ-bCnPPMYp6QIfrCr2BR-imm_Sw9IHCXIXzE5fei7R8PTBKYGd'>
  <div id='caption-wrap'>
    <p>some text will appear</p>
  </div>
</div>

Codepen: https://codepen.io/bergy/pen/YoxZBp

(edit: since the JS was getting the rects outside of the mouse move function, if the element was ever moved it would stop working. Now it looks for rects in mouse move so the bug is fixed)



Source: stackoverflow