Search code examples
csssvghovercross-browserpointer-events

CSS :hover on SVG group area instead of rendered pixels, pointer-events: bounding-box not working cross browser. How to workaround


I'm working on some animated SVGs with CSS animations that triggers on hover. I'm being able to have the SVG animate on hover the way I want to for Chrome but I'm facing a Firefox and Safari issue.

Apparently, the pointer-events property applied to groups <g></g> doesn't give same behavior on this browser than on the other modern ones, at least when trying to set the value to bounding-box.

I'm doing

g {
  pointer-events: bounding-box;
}

but the hover only gets triggered when the actual <path> element is hovered, not the whole group <g> as I would need to.

Can I use doesn't say anything about this, it mentions svgs also have support for this property.

Below there's a sample code for you to see how one of my SVGs looks like. On chrome hovering the main containing group area will trigger the hover animation, on Firefox the actual path (the icon lines in this case) needs to be hovered in order to that to happen.

<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
    <style>
        g {
            pointer-events: bounding-box;     
            //not working on FF
        }
        #mobile:hover .flip {
            transform-origin:55% 50%;
            -moz-transform-origin:55% 50%;
            animation: flip_left 1.6s forwards;
        }
        @keyframes flip_left {
          0% {transform: perspective(2000px) rotateY(90deg) skewY(-1deg)}
          30% {transform:perspective(2000px) rotateY(-25deg) skewY(-0.8deg)}
          50% {transform:perspective(2000px) rotateY(20deg) skewY(0.8deg)}
          70% {transform:perspective(2000px) rotateY(-10deg) skewY(-0.8deg)}
          100% {transform:perspective(2000px) rotateY(0deg)}
        }
    </style>
    <!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
    <title>Mobile solutions</title>
    <desc>Created with Sketch.</desc>
    <defs></defs>
    <g id="mobile" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke-width="1.25">
            <g id="Asset-5" transform="translate(766.000000, 418.000000)">
                <g class="flip">
                <rect id="Rectangle-path" stroke-linecap="round" stroke-linejoin="round" x="12.35" y="7.41" width="15.32" height="25.33" rx="2.03"></rect>
                <circle id="Oval" stroke-linecap="round" stroke-linejoin="round" cx="20.01" cy="28.72" r="1.58"></circle>
                <path d="M18.43,10.72 L21.48,10.72" id="Shape" stroke-linecap="round" stroke-linejoin="round"></path>
            </g>
                <circle id="Oval" cx="19.67" cy="19.67" r="19.04"></circle>
            </g>
        </g>
    </g>
</svg>

I would like to find a workaround for this, since I want to make this animations work cross browser. I would like to eventually make it work for IE11 and Edge too.

Thanks,


Solution

  • So pointer-events: bounding-box seems to not be supported by most browsers.

    I implemented the workaround @ccprog suggested on the comments section of my question.

    I added a <rect fill="none"> element to svg, that is same dimensions than the SVG itself. I added a :hover selector for that element and sibling selector ~ to select its sibling group with the flip class inside.

    See CSS:

    #mobile-hover {
       visibility: visible;
       pointer-events: visible;
    }
    #mobile-hover:hover ~ .group .flip {
      -moz-transform-origin:55% 50%;
      -webkit-transform-origin: 55% 50%;
      transform-origin:55% 50%;
      -webkit-animation: flip_left 1.6s forwards;
      animation: flip_left 1.6s forwards;
    }
    

    I found out I had to add pointer-events: visible to the rect element so it would detect the :hover. I added visibility: visible as a requirement to pointer-events: visible to work.

    Below the full new SVG code:

    <?xml version="1.0" encoding="UTF-8"?>
    <svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="mobile-icon">
        <style>
            #mobile-hover {
            visibility: visible;
            pointer-events: visible;
            }
            #mobile-hover:hover ~ .group .flip {
                -moz-transform-origin:55% 50%;
                -webkit-transform-origin: 55% 50%;
                transform-origin:55% 50%;
                -webkit-animation: flip_left 1.6s forwards;
                animation: flip_left 1.6s forwards;
            }
            @keyframes flip_left {
              0% {transform: perspective(2000px) rotateY(90deg) skewY(-1deg)}
              30% {transform:perspective(2000px) rotateY(-25deg) skewY(-0.8deg)}
              50% {transform:perspective(2000px) rotateY(20deg) skewY(0.8deg)}
              70% {transform:perspective(2000px) rotateY(-10deg) skewY(-0.8deg)}
              100% {transform:perspective(2000px) rotateY(0deg)}
            }
        </style>
        <!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
        <title>Mobile solutions</title>
        <desc>Created with Sketch.</desc>
        <defs></defs>
        <g id="mobile" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" >
        <rect fill="none" width="40" height="40" id="mobile-hover">
        </rect>
            <g id="MS_HP_Usecase_Based_Page-Desktop-2A" transform="translate(-766.000000, -418.000000)" stroke="#00A0DF" stroke-width="1.25" class="group">
                <g id="Asset-5" transform="translate(766.000000, 418.000000)">
                    <g class="flip">
                    <rect id="Rectangle-path" stroke-linecap="round" stroke-linejoin="round" x="12.35" y="7.41" width="15.32" height="25.33" rx="2.03"></rect>
                    <circle id="Oval" stroke-linecap="round" stroke-linejoin="round" cx="20.01" cy="28.72" r="1.58"></circle>
                    <path d="M18.43,10.72 L21.48,10.72" id="Shape" stroke-linecap="round" stroke-linejoin="round"></path>
                </g>
                    <circle id="Oval" cx="19.67" cy="19.67" r="19.04"></circle>
                </g>
            </g>
    
        </g>
    </svg>
    

    Works on Chrome, Safari and Firefox and I'm attempting to test IE11 and Edge next.

    Many thanks,