Add hover style inside SVG file or tag

When you set it as the content of a pseudo element, your svg is actually a CSS <image>. CSS <image> representing svg documents have the same restrictions as html <img> representing svg:

  • No external resources will get fetched
  • Scripts won't run in the inner document
  • The inner document won't be interactive (i.e no pointer-events)
  • ...

This means that any :hover style in this svg document will be useless.

What you can do however is to set this :hover on the parent .slick-next element and change the content there.

To avoid having to store two svg files on your servers with only the fill that will change, you can use of a hack demonstrated by Lea Verou, which exploits the :target pseudo-class. More info on this here.

You would have to restructure your svg so that you have invisible triggerer elements with [id] attributes, so they can become :target. Then all the logic is made using CSS selectors:

right_arrow.svg

<svg width="28" height="81" viewBox="0 0 28 81" xmlns="http://www.w3.org/2000/svg">
  <style>
    .slick_next_arrow {
      fill:red;
    }
    /* when loaded from 'right_arrow.svg#hover' */
    #hover:target ~ .slick_next_arrow {
      fill:green;
    }
  </style>
  <!-- here is our triggerer -->
  <g id="hover"></g>
  <!-- the visual content -->
  <path class="slick_next_arrow" hover="fill:green" fill-rule="evenodd" clip-rule="evenodd" d="M3.73141 1.20959C2.95311 -0.00927037 1.3341 -0.366415 0.115239 0.411883L25.5894 40.3058L0 80.3802C1.21886 81.1585 2.83787 80.8014 3.61617 79.5825L27.4729 42.2216C27.7642 41.7653 27.8965 41.2531 27.884 40.7498C28.1017 40.0409 28.0185 39.2445 27.5881 38.5705L3.73141 1.20959Z"/>
</svg>

And your CSS:

.slick__arrow .slick-next::after {
  content : url('right_arrow.svg');
}
.slick__arrow .slick-next:hover::after {
  content : url('right_arrow.svg#hover');
}

Here is a more complex live-snippet since we have to workaround the fact we can't host third party files from StackSnippets.

const svg_content = `<svg width="28" height="81" viewBox="0 0 28 81" xmlns="http://www.w3.org/2000/svg">
  <style>
    .slick_next_arrow {
      fill:red;
    }
    #hover:target ~ .slick_next_arrow {
      fill:green;
    }
/* some goodies */
    circle {
      display: none;
    }
    /* hide previous path */
    [id^="show_circle"]:target ~ .slick_next_arrow {
      display: none;
    }
    /* show new one */
    [id^="show_circle"]:target ~ circle {
      display: block; 
      fill: red;
    }
    #show_circle_hover:target ~ circle.change-color {
      fill: green;
    }
  </style>
  <!-- here are all our triggerers -->
  <g id="hover"></g>
  <g id="show_circle"></g>
  <g id="show_circle_hover"></g>
  <path class="slick_next_arrow" hover="fill:green" fill-rule="evenodd" clip-rule="evenodd" d="M3.73141 1.20959C2.95311 -0.00927037 1.3341 -0.366415 0.115239 0.411883L25.5894 40.3058L0 80.3802C1.21886 81.1585 2.83787 80.8014 3.61617 79.5825L27.4729 42.2216C27.7642 41.7653 27.8965 41.2531 27.884 40.7498C28.1017 40.0409 28.0185 39.2445 27.5881 38.5705L3.73141 1.20959Z"/>
  <circle cx="14" cy="15" r="12"/>
  <circle cx="14" cy="40" r="12" class="change-color"/>
  <circle cx="14" cy="65" r="12"/>
</svg>`;

// StackSnippets force us to make a complex js-powered live demo...
// but in production all is done from CSS
const url = URL.createObjectURL( new Blob( [ svg_content ], { type: "image/svg+xml" } ) );

const el = document.querySelector( '.parent' );
el.style.setProperty( '--url', 'url(' + url + ')' );
el.style.setProperty( '--url-hovered', 'url(' + url + '#hover)' );
el.style.setProperty( '--url-circle', 'url(' + url + '#show_circle)' );
el.style.setProperty( '--url-circle-hovered', 'url(' + url + '#show_circle_hover)' );
.parent{
  display: inline-block;
  width: 28px;
  height: 90px;
}
.parent::before {
  /* right_arrow.svg */
  content: var(--url);
}
.parent:hover::before {
  /* right_arrow.svg#hover */
  content: var(--url-hovered);
}
/* goodies */
:checked ~ .parent::before {
  /* right_arrow.svg#show_circle */
  content: var(--url-circle);
}
:checked ~ .parent:hover::before {
  /* right_arrow.svg#show_circle_hover */
  content: var(--url-circle-hovered);
}
<input type="checkbox" id="check"><label for="check">change shape</label><br>
<div class="parent"></div>

But you can access the simple version in this plnkr.

Tags:

Html

Css

Svg