Inline SVG hover states
with CSS (<use> tag)

The article is about a really, really, really! simple hover states trick when you use SVG’s with the <use> tag.


The problem

At the time of creating this little trick I nearly hadn’t any knowledge of SVG’s. The project I was working on, was that big that it literally screamed to use icons like an icon font generated with IcoMoon.

But something was bothering me about the icon fonts. At several projects some icons where, for an unknown reason, more blurry than other icons in that the generated font.

Arghhh! Why?

I found an article from Chris Coyier about Inline SVG’s versus Icon Fonts. Where he directly pointed out my problem.

In a recent personal example, while converting some icons from fonts to SVG on CodePen, some of the font icons were noticeably less sharp than the ones I converted over.

This article made me make the switch to inline SVG’s. Because there was a need of fully sharp icons in all situations. Keep in mind that inline SVG’s aren’t supported by IE8, but hey who is supporting this anyway?


The Task

But there was one more challenge. How could I simply create a hover effect on an SVG with the knowledge I had about it those days?
I needed 4 kind of states:

  • Default
  • Hover
  • Active
  • Active - hover

Creating icons

I generated the SVG sprite with IcoMoon which is making use of the <use> tag. The next step was combining some SVG’s to make a “like” button which, in this case, I was working on.

<svg class="icon" viewBox="0 0 32 32">
<use xlink:href="#icon-like-default"></use>
<use xlink:href="#icon-like-hover"></use>
<use xlink:href="#icon-like-active"></use>
<use xlink:href="#icon-like-active-hover"></use>
</svg>

As you can imagine the icons are all displayed on top of each other. Demo Next I added the states as classnames, like:

<svg class="icon" viewBox="0 0 32 32">
<use class="default" xlink:href="#icon-like-default"></use>
<use class="hover" xlink:href="#icon-like-hover"></use>
<use class="active" xlink:href="#icon-like-active"></use>
<use class="active-hover" xlink:href="#icon-like-active-hover"> </use>
</svg>

Hide and Seek

Now CSS must help us do the trick. First I created 2 silent classes. (SCSS)
This is just a opacity switch. You could also use display:none/block; but in this case I had to add opacity to create some awesome transitions. :’)

%icon{
&-is-shy{
opacity: 0;
}
&-isnt-shy{
opacity: 1;
}
}

After that I add the states as classnames in SCSS as children of the .icon class. Hide them by default except the default icon of course.

.hover, .active, .active-hover{
@extend %icon-is-shy;
}

Followed up by adding the different states:

:hover
It says; Only trigger me when I don’t have the ‘active’ class.

&:not(.active):hover{

.hover{
@extend %icon-isnt-shy;
}
    .default{
@extend %icon-is-shy;
}
}

Active

&.active{
.default{
@extend %icon-is-shy;
}
    .active{
@extend %icon-isnt-shy;
}
}

Active :hover

&.active:hover{
.active{
@extend %icon-is-shy;
}

.active-hover{
@extend %icon-isnt-shy;
}
}

Making it work

The last part is a tiny part of JavaScript that triggers a class on the SVG tag. Which will add the .active class.

$(“.icon”).click( function() { 
var c = $(this).attr(‘class’);

if(c == “icon active”){
$(this).attr(‘class’, ‘icon’);
return true;
}

$(this).attr(‘class’, ‘icon active’);
});

Demotime

See that simplicity in action:
nicknoordijk.me/blog/inline-svg-hover-states-css-tag/

P.S. : This is my very first writing on the web, so tips are welcome!

Show your support

Clapping shows how much you appreciated Nick Noordijk’s story.