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

Nick Noordijk
Oct 4, 2014 · 3 min read

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

The problem

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?

Image for post
Image for post

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

  • Default
  • Hover
  • Active
  • Active - hover

Creating icons

<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

%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

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

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

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

Demotime

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

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store