Styling a Hover Statement in Svg

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 CSSconst 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>

styling a hover statement in SVG

It can be done fairly simply. But it requires a little javascript.

Here's a simplified example with just three circles. Hopefully it should be obvious how to add the other two circles and the rest of the lines. The JS and CSS should work as is for any number of circles and lines.

window.addEventListener('DOMContentLoaded', (event) => {

var allCircles = document.querySelectorAll("circle");

// Add an click handler to every circle that
// adds the class "active" to the clicked circle.
allCircles.forEach(element => {
element.addEventListener("click", clickHandler);
element.addEventListener("mouseover", mouseoverHandler);
element.addEventListener("mouseout", mouseoutHandler);
});

});

function clickHandler(evt) {
// Clear current selection (remove class "active" from any circle)
allCircles.forEach((circle) => circle.classList.remove("active"));
// Mark clicked circle selected
evt.target.classList.add("active");
// Clear any currently highlighted lines
clearHighlightedLines();
}

function mouseoverHandler(evt) {
let activeCircle = document.querySelector("circle.active");
let hoveredCircle = evt.target;
if (activeCircle && (activeCircle != hoveredCircle)) {
// Get the line that has classes matching both the actibve and hovered circle
let line = document.querySelector("line."+activeCircle.id+"."+hoveredCircle.id);
// Add the class "highlight" to that line
if (line)
line.classList.add("highlight");
}
}

function mouseoutHandler(evt) {
clearHighlightedLines();
}

function clearHighlightedLines() {
// Find the line with class "highlight" (if any)
var line = document.querySelector("line.highlight");
// Remove the class "highlight"
if (line)
line.classList.remove("highlight");
}
#c3 {
fill: maroon;
}

#c4 {
fill: steelblue;
}

#c5 {
fill: rebeccapurple;
}

circle:hover:not(.active) {
stroke: #999;
stroke-width: 1.5;
}

circle.active {
stroke: black;
stroke-width: 1.5;
}

line {
stroke: gold;
stroke-width: 1;
}

line.highlight {
stroke: black;
}
<svg viewBox="0 0 100 100">


<!-- line from c3 to c4 -->
<line x1="75" y1="40" x2="25" y2="70" class="c3 c4"/>

<!-- line from c3 to c5 -->
<line x1="75" y1="40" x2="57" y2="70" class="c3 c5"/>

<!-- line from c4 to c5 -->
<line x1="25" y1="70" x2="57" y2="70" class="c4 c5"/>

<circle id="c3" cx="75" cy="40" r="10"/>

<circle id="c4" cx="25" cy="70" r="10"/>

<circle id="c5" cx="57" cy="70" r="10"/>

</svg>

How to change the color of the SVG when hovering over the image?

Just add the :hover pseudoclass onto the image instead of the svg. Also, you should use 'fill' instead of background-color for svgs to properly fill in only the path :)

If you want the middle triangle to be white permanently (like in the link's video), you'll need to add another path to the svg and fill that with white.

EDIT: added the center play button path (just copied the SVG from the referenced page + its viewbox) and changed opacity when hovered.

#youtube-remote,
#youtube-remote .youtube-remote-container {
display: flex;
justify-content: center;
align-items: center;
}

#youtube-remote svg {
position: absolute;
opacity: 0.8;
}

#youtube-remote:hover svg {
opacity: 1;
}

#youtube-remote:hover .play-outer {
fill: red;
}
   

<div id="youtube-remote">
<a href="https://www.youtube.com" target="_blank">
<div class="youtube-remote-container">
<img src="https://img.youtube.com/vi/ZLga1SIE1HA/maxresdefault.jpg" width="1280" height="720" alt="Sample Image" loading="lazy">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 68 48">
<path class="play-outer" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z"/>
<path d="M 45,24 27,14 27,34" fill="white"/>
</svg>
</div>
</a>
</div>

How to change svg fill on hover

Your problem is that you are styling the original exit SVG on hover. That particular one should work.

However all the other buttons that use <svg><use> will not work because when you hover over them, the mouse event doesn't get passed through to the original one (that use points to).

Instead, you should attach the hover rule to the <svg><use> elements instead.
You can apply a style to them, and it will inherited by the original used instance.

.exit {
width: 47.63px;
height: 47.63px;
border: none;
background: none;
padding: 0;
}

.exit:hover svg {
fill: green;
}
<p>original</p>
<button class="exit" type="button" aria-label="Close">
<svg width="100%" height="100%" viewBox="-144 -144 288 288">
<g id="exit">
<title>exit</title>
<circle class="exitCircle" cx="0" cy="0" r="144" fill="transparent"/>
<path class="exitHover" d="m-143 0a143 143 0 1 1 286 0 143 143 0 0 1 -286 0m128-112a113 113 0 0 0 -97 97h97zm-97 127a113 113 0 0 0 97 97v-97zm127 97a113 113 0 0 0 97 -97h-97zm97-127a113 113 0 0 0 -97 -97v97z" transform="rotate(45)" fill="red" />
</g>
</svg>
</button>

<p><use></p>
<button class="exit" type="button" aria-label="Close">
<svg width="100%" height="100%" viewBox="-144 -144 288 288">
<use href="#exit" />
</svg>
</button>


Related Topics



Leave a reply



Submit