1

I have been experimenting with inline svg for the first time. Here is my code:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="350" height="350">
  <defs>
    <style>
      .ring {
        transform-origin: 175px 175px;
      }

      .ring.a {
        fill: #f2ca30;
      }
      .ring.b {
        fill: #31bc06;
      }
      .ring.c {
        fill: #11a0ad;
        }
      .ring.d {
        fill: #028d9e;
      }

      .btn.tap.area {
        z-index: 100;
        fill: transparent;
      }
      .btn.tap.area:hover + .ring.container .ring {
        animation-iteration-count: infinite;
        animation-timing-function: linear;
      }

      .btn.tap.area:hover + .ring.container .ring.a,
      .btn.tap.area:hover + .ring.container .ring.c {
        animation-name: clockwise;
      }
      .btn.tap.area:hover + .ring.container .ring.b,
      .btn.tap.area:hover + .ring.container .ring.d {
        animation-name: counter-clockwise;
      }

      .btn.tap.area:hover + .ring.container .ring.a {
        animation-duration: 1.33s;
      }
      .btn.tap.area:hover + .ring.container .ring.b {
        animation-duration: 1s;
      }
      .btn.tap.area:hover + .ring.container .ring.c {
        animation-duration: .67s;
      }
      .btn.tap.area:hover + .ring.container .ring.d {
        animation-duration: .33s;
      }

      @keyframes clockwise {
        from {
          transform: rotate(0deg);
        }
        to {
          transform: rotate(360deg);
        }
      }
      @keyframes counter-clockwise {
        from {
          transform: rotate(0deg);
        }
        to {
          transform: rotate(-360deg);
        }
      }
    </style>
  </defs>
  <title>ring btn</title>
  <rect class="btn tap area" width="350" height="350"/>
  <g class="ring container">
    <path class="ring a" d="M119.139,129.639a10.5,10.5,0,0,1-7.425-17.924,89.5,89.5,0,0,1,126.571,0,10.5,10.5,0,0,1-14.849,14.85,68.5,68.5,0,0,0-96.873,0A10.468,10.468,0,0,1,119.139,129.639Z"/>
    <path class="ring b" d="M104.29,114.79a10.5,10.5,0,0,1-7.425-17.924,110.5,110.5,0,0,1,156.269,0,10.5,10.5,0,1,1-14.849,14.85,89.5,89.5,0,0,0-126.57,0A10.468,10.468,0,0,1,104.29,114.79Z"/>
    <path class="ring c" d="M89.44,99.94a10.5,10.5,0,0,1-7.424-17.925,131.5,131.5,0,0,1,185.967,0,10.5,10.5,0,1,1-14.849,14.85,110.5,110.5,0,0,0-156.27,0A10.468,10.468,0,0,1,89.44,99.94Z"/>
    <path class="ring d" d="M74.591,85.091a10.5,10.5,0,0,1-7.425-17.925,152.5,152.5,0,0,1,215.667,0,10.5,10.5,0,1,1-14.849,14.85,131.5,131.5,0,0,0-185.968,0A10.468,10.468,0,0,1,74.591,85.091Z"/>
  </g>
</svg>

At a first glance this btn seems to work fine once you :hover into the .btn.tap.area I have defined. But if your cursor happens to get in the way of one of the animated .ring paths then the animation seems to get re-triggered and starts again.

I would like sole this re-triggering issue without any JS.

My solution to this was to put the transparent .btn.tap.area atop of the other paths in the svg.

I can't change the rendering order of my svg paths as I am relying on it in the css e.g. .btn.tap.area:hover + .ring.container .ring.a {.

As I understand it z-index isn't valid in the context of svg, so I cannot use that.

I then saw this post and thought that the alternative solution offered would work: <use xlink:href="#btnID"/> would call up a second instance of the .btn.tap.area path once I had added an id of btnID to .btn.tap.area. But this didn't seem to work either.

Is there another solution to force the .btn.tap.area in front of the other paths without using any JS?

Here is a fiddle to see the issue for yourself.

Community
  • 1
  • 1
DanMad
  • 1,643
  • 4
  • 23
  • 58
  • place your rect inside the g.container, set your CSS :hover rules on the g element and you're done. – Kaiido Nov 16 '16 at 08:18

2 Answers2

1

You can't change svg elements order with z-index. But you can do it with HTML elements. What about the following solution :

I put the tap-area in another absolutely-positioned svg.

  .svg-stack {
    position: relative;
  }
      
  .svg-tap-area {
    position: absolute;
    z-index: 1;
  }
      
  .ring {
    transform-origin: 175px 175px;
  }

  .ring.a {
    fill: #f2ca30;
  }

  .ring.b {
    fill: #31bc06;
  }

  .ring.c {
    fill: #11a0ad;
  }

  .ring.d {
    fill: #028d9e;
  }

  .btn.tap.area {
    fill: transparent;
  }

  .svg-tap-area:hover + svg .ring.container .ring {
    animation-iteration-count: infinite;
    animation-timing-function: linear;
  }

  .svg-tap-area:hover + svg .ring.container .ring.a,
  .svg-tap-area:hover + svg .ring.container .ring.c {
    animation-name: clockwise;
  }

  .svg-tap-area:hover + svg .ring.container .ring.b,
  .svg-tap-area:hover + svg .ring.container .ring.d {
    animation-name: counter-clockwise;
  }

  .svg-tap-area:hover + svg .ring.container .ring.a {
    animation-duration: 1.33s;
  }

  .svg-tap-area:hover + svg .ring.container .ring.b {
    animation-duration: 1s;
  }

  .svg-tap-area:hover + svg .ring.container .ring.c {
    animation-duration: .67s;
  }

  .svg-tap-area:hover + svg .ring.container .ring.d {
    animation-duration: .33s;
  }

  @keyframes clockwise {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }

  @keyframes counter-clockwise {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(-360deg);
    }
  }
<div class="svg-stack">
  <svg class="svg-tap-area" xmlns="http://www.w3.org/2000/svg" version="1.1" width="350" height="350">
    <title>ring area</title>
    <rect class="btn tap area" id="one" width="350" height="350"/>
  </svg>

  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="350" height="350">
    <title>ring btn</title>
    <g class="ring container">
      <path class="ring a" d="M119.139,129.639a10.5,10.5,0,0,1-7.425-17.924,89.5,89.5,0,0,1,126.571,0,10.5,10.5,0,0,1-14.849,14.85,68.5,68.5,0,0,0-96.873,0A10.468,10.468,0,0,1,119.139,129.639Z"/>
      <path class="ring b" d="M104.29,114.79a10.5,10.5,0,0,1-7.425-17.924,110.5,110.5,0,0,1,156.269,0,10.5,10.5,0,1,1-14.849,14.85,89.5,89.5,0,0,0-126.57,0A10.468,10.468,0,0,1,104.29,114.79Z"/>
      <path class="ring c" d="M89.44,99.94a10.5,10.5,0,0,1-7.424-17.925,131.5,131.5,0,0,1,185.967,0,10.5,10.5,0,1,1-14.849,14.85,110.5,110.5,0,0,0-156.27,0A10.468,10.468,0,0,1,89.44,99.94Z"/>
      <path class="ring d" d="M74.591,85.091a10.5,10.5,0,0,1-7.425-17.925,152.5,152.5,0,0,1,215.667,0,10.5,10.5,0,1,1-14.849,14.85,131.5,131.5,0,0,0-185.968,0A10.468,10.468,0,0,1,74.591,85.091Z"/>
    </g>
    <rect class="btn tap area" id="one" width="350" height="350"/>
  </svg>
</div>
Manuszep
  • 813
  • 11
  • 20
1

Add pointer-events: none; to the ring elements e.g.

  .ring {
    transform-origin: 175px 175px;
    pointer-events: none;
  }
Robert Longson
  • 118,664
  • 26
  • 252
  • 242