Controlling SVG via CSS for transitions and hover effects

While developing a website, one of the biggest problem we normally get is icon distortion if we are using png/jpg icons specially on retina/HD screens. In order to avoid this problem we use SVG’s icon.

SVG icon is a very good idea but it also have pros and cons which we will discuss in dept below.

Lets create a simple SVG task in which we will add SVG image (blue colour) with hover effect (red colour). In order to achieve this we have normally two ways to do it.

1. Adding SVG inside HTML files

So lets add SVG file directly to HTML file.

<html>
<head>
<meta charset="UTF-8">
<title>SVG</title>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<h1>Adding SVG</h1>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 39.17 40.18"><defs><style>.cls-1{fill:#00ade5;}</style></defs><title>calender</title><g id="final_footer" data-name="final footer"><path class="cls-1" d="M2738.84,1401.65a4.13,4.13,0,0,0,4.13,4.13h30.86a4.13,4.13,0,0,0,4.13-4.13V1379h-39.12v22.64Zm26.77-18.55h4.13v4.13h-4.13v-4.13Zm0,6.2h4.13v4.13h-4.13v-4.13Zm0,6.15h4.13v4.13h-4.13v-4.13Zm-6.2-12.35h4.13v4.13h-4.13v-4.13Zm0,6.2h4.13v4.13h-4.13v-4.13Zm0,6.15h4.13v4.13h-4.13v-4.13Zm-6.15-12.35h4.13v4.13h-4.13v-4.13Zm0,6.2h4.13v4.13h-4.13v-4.13Zm0,6.15h4.13v4.13h-4.13v-4.13Zm-6.2-12.35h4.13v4.13h-4.13v-4.13Zm0,6.2h4.13v4.13h-4.13v-4.13Zm0,6.15h4.13v4.13h-4.13v-4.13Z" transform="translate(-2738.8 -1365.6)"/><path class="cls-1" d="M2773.83,1368.72h-4.13v-1.06a2,2,0,1,0-4.09,0v1h-14.42v-1a2.06,2.06,0,0,0-2.07-2.07,2.09,2.09,0,0,0-2.07,2.07v1h-4.13a4.13,4.13,0,0,0-4.13,4.13v4.13h39.12v-4.13A4.05,4.05,0,0,0,2773.83,1368.72Z" transform="translate(-2738.8 -1365.6)"/></g></svg>
</body>
</html>

Now we will add css to get hover effect

svg {
width: 100px;
height: 100px;
}
svg:hover path {
fill: red;
}
calendar SVG image

You can see the working example from the link below
https://jsfiddle.net/asadalikanwal/7wu975f9/

Yahoo.. we have completed our task. It was very easy to do

PROS: Can be control via CSS completely, changing hover colour and adding transitions are very easy.

CONS: SVG code shows on HTML due to which looks very messy. Imagine if we have 10 SVG images on a page than it would be very untidy code.

2. Adding SVG inside <img> tag

Lets add SVG image inside <img> tag

<img src="img/calendar.svg" />

This looks very simple and tidy, but unfortunately CSS will not work now because inside <img> tag there is no SVG path

svg {
width: 100px;
height: 100px;
}
svg:hover path {
fill: red;
}

Which means in order to complete our task we have to use 2 SVG image. First Image with SVG (blue) colour and second Image with SVG (RED)

SVG Image 1 with blue color
SVG Image 2 with red color

Now, this is not a good idea to use 2 images. Just imagine if we have 15 SVG images then we have to generate 15 x 2 = 30 SVG images.

PROS : HTML code looks very tidy and clean

CONS : Can’t control via css, have to use 2 SVG Images

Best solution is to merge option 1 and option 2 to achieve clean, tidy and controllable SVG

Lets create HTML file and use SVG inside <img> tag.

<html>
<head>
<meta charset="UTF-8">
<title>SVG</title>
<link href="style.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="svg-img.js"></script>
</head>
<body>
<h1>Adding SVG</h1>
<img src="img/calender.svg" class="svg" />
</body>
</html>

Note, above we have add JQUERY , svg-img.js and on <img> tag i have put 1 class “svg

JQUERY : Is the jquery lib, which we can get from http://www.jquery.com
svg-img.js : Is our custom javascript file which check for SVG inside <img> tag and convert it to SVG file on rendering. Make sure you add “svg” class on <img> tag

Now let see Svg-img.js — (Got this JS when i was reading different articles on SVG, but I have changed this code little bit)

/*
* Replace all SVG images with inline SVG
*/
$(function() {
$('img.svg').each(function() {
var $img = $(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
$.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = $(data).find('svg');
// Add replaced image's ID to the new SVG
if (typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass + ' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
})

This JS converts all the <img> tag which has “svg” class into SVG tag

And lastly lets add CSS with transitions and hover effects

.svg {
width: 100px;
height: 100px;
}
svg path,
svg circle {
-webkit-transition: all .5s ease;
-moz-transition: all .5s ease;
-ms-transition: all .5s ease;
-o-transition: all .5s ease;
}
svg:hover path {
fill: red;
}

Now, lets see the output

On the right hand side you can see in our HTML file we are using <img> tag with “svg” class but when page renders on browser it automatically convert it to a <svg> tag which you can see on the left hand side.

Finally, we have achieved our task with full CSS control. If you have any questions do write me. You can download updated code from Github