0

I'm adding an overlaid box on an image so that the box's borders are interactable but pointer-events pass through its unfilled center. Reading MSDN I thought the phrase "experimental for HTML" meant modern browsers might run it for HTML:

MSDN pointer-events documentation:

visible

SVG only (experimental for HTML). The element can be the target of a pointer event when the visibility property is set to visible and e.g. the mouse cursor is over either the interior (i.e., fill) or the perimeter (i.e., stroke) of the element. The values of the fill and stroke do not affect event processing.

So I tried:

#overlay {
  position: absolute;
  left: 50px;
  top: 50px;
  width: 200px;
  height: 100px;
  border-width: 2px;
  border-color: lime;
  border-style: solid;
  pointer-events: visible;
}
#puppy:hover{
  opacity: 0.5
}
<img id="puppy" src="https://live.staticflickr.com/4112/5170590074_714d36db83_b.jpg" />
<div id="overlay"></div>

But this fails. I then tried to get into creating and resizing SVG elements dynamically and somehow that appears to be a bit more complicated, having to update viewBoxes and setting namespaceURIs and such... Maybe it's not that bad but I'd really prefer to just use HTML, it leaves my code cleaner.

J.Todd
  • 707
  • 1
  • 12
  • 34

2 Answers2

2

To achieve this you could use a clip-path to create a real hole in your element, letting even pointer-events go through:

#overlay {
  position: absolute;
  left: 50px;
  top: 50px;
  width: 200px;
  height: 100px;
  
  --border-size: 6px;
  clip-path: polygon( evenodd,
    0 0, /* top - left */
    100% 0, /* top - right */
    100% 100%, /* bottom - right */
    0% 100%, /* bottom - left */
    0 0, /* and top - left again */
    /* do the same with inner rect */
    var(--border-size) var(--border-size),
    calc(100% - var(--border-size)) var(--border-size),
    calc(100% - var(--border-size)) calc(100% - var(--border-size)),
    var(--border-size) calc(100% - var(--border-size)),
    var(--border-size) var(--border-size)
  );
  /*
    the border-color can now be set through the background property
    which means we could even have corner-gradients borders
  */
  background: lime;
}
#puppy:hover{
  opacity: 0.5
}
<img id="puppy" src="https://live.staticflickr.com/4112/5170590074_714d36db83_b.jpg" />
<div id="overlay"></div>

With a bit more work, you can even achieve more complex shapes for the hole.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
0

Found the answer on CSS-tricks:

  1. You know how if you display: hidden; an element, even if you display: block; a child, it doesn’t matter — it’s hidden because its parent is hidden.
  2. The same is not true for visibility: hidden;. Children will be hidden because visibility inherits, but if you visibility: visible; them, they become visible again.
  3. That’s what is happening here with pointer-events. If you pointer-events: none; on a parent and then pointer-events: auto; on a child, you’re re-enabling pointer events. Then a :hover on a parent will be triggered (for example), when hoving the child, but nowhere else inside the parent.

#overlay {
  position: absolute;
  left: 50px;
  top: 50px;
  width: 200px;
  height: 100px;
  pointer-events: none;
}

#overlay>div {
  position: absolute;
  background-color: lime;
  width: 2px;
  height: 2px;
  pointer-events: auto;
}

#overlay>div:hover {
  background-color: pink;
}

#overlay>div:nth-child(1) {
  top: 0%;
  left: 0%;
  width: 100%;
}
#overlay>div:nth-child(2) {
  top: 100%;
  left: 0%;
  width: 100%;
}
#overlay>div:nth-child(3) {
  top: 0%;
  left: 100%;
  height: 100%;
}
#overlay>div:nth-child(4) {
  top: 0%;
  left: 0%;
  height: 100%;
}

#puppy:hover{
  opacity: 0.5
}
<img id="puppy" src="https://live.staticflickr.com/4112/5170590074_714d36db83_b.jpg" />
<div id="overlay">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>
J.Todd
  • 707
  • 1
  • 12
  • 34