Why do the mouseenter/mouseleave events fire when entering/leaving child elements in an SVG?
Asked Answered
T

1

7

I have an SVG, inside which there are more SVGs with a variable number of rect elements inside them, all generated from a data object. Here's the general hierarchy:

<svg class="parent-svg">
    <svg class="child-svg">
        <rect />
        <rect />
    </svg>
    <svg class="child-svg">
        <rect />
        <rect />
    </svg>
</svg>

I've bound mouseenter/mouseleave events to the .child-svg elements, but I'm finding that the events are firing when my mouse goes to the whitespace in between the <rect> elements. My understanding of mouseenter/mouseleave is that they shouldn't fire when the cursor enters/leaves the child elements -- this seems like behaviour you'd expect from mouseover/mouseout. And of course, what I'd ideally like is for the mouseenter/mouseleave events only to fire when I've left each section (which I've delineated using colours).

Here's the relevant fiddle: http://jsfiddle.net/ysim/yVfuK/4/

Edit: I tried giving the .child-svg elements a height and width, but that didn't seem to work either: http://jsfiddle.net/ysim/gMXuU/3

Edit: Here's the fiddle with the solution, fixed according to @pornel's suggestion: http://jsfiddle.net/ysim/HUHAQ/

Thanks!

Tc answered 21/6, 2013 at 22:2 Comment(5)
What browser are you using? It seems to have the desired effect for me.Suber
Read about event propagation #4617194Adelina
Is that really SVG-in-SVG rather than <g>?Hally
@AlexMorrise: I tried it on Chrome, Firefox, and Safari... it didn't work on any of them. Which browser are you using?Tc
@porneL: Yes, it's definitely SVG-in-SVG. I tried it with <g> and it seems that the mouseenter event handler is bound to each of its child elements, which isn't what I want.Tc
H
8

My guess is that .child-svg doesn't have any area on its own, so there is no way to hover it directly. When mouse leaves <rect> it leaves .child-svg too.

SVG doesn't have flow layout, so children don't affect size of parent element.


Here's solution: http://jsfiddle.net/gMXuU/4/

  • add a <rect> with no fill as background
  • add pointer-events:all to make invisible element "visible" to the mouse pointer
Hally answered 21/6, 2013 at 22:50 Comment(3)
The <svg> elements are containers and have no clickable area themselves (this changes if they have a solid background, e.g using the viewport-fill property).Spigot
I had a bit simpler case... a DIV that displayed a child SVG. I had mouseenter, mouseleave, and click handlers for the DIV, but the SVG was causing unwanted mouseleave and mouseenter events on the DIV. After reading Kornel's answer I found that applying style pointer-events: none to the SVG prevented the unwanted behavior. IOW, the SVG no longer existed from mouse's perspective. Perfect! Thanks for the tip about pointer-events Kornel!Vauban
Thank you for this answer. pointer-events saved my ass. I had this weird bug where mouseleave is fired when the pointer is still on the element. This answer helped me found out this is because the container changes its pointer-events back and forth depending on scroll.Adriaadriaens

© 2022 - 2024 — McMap. All rights reserved.