Animate infographics with SVG and CSS3

Deliver clear world map infographics by making use of CSS3


Maps have been delivered throughout the web for a long time and most web teams have implemented basic mapping, if only to display the surrounding geography of a particular location.

With accurate, interactive JavaScript-powered maps just an API away, stylistic maps often take a backseat on the contemporary web. Stylistic maps have also been quite difficult to get right historically – trading detail and accuracy for file size, legibility and aesthetics.
However, with the evergreen browsers now having good support for SVG, crafting crisp and clear stylistic map experiences is easier than ever before. Using contemporary techniques it’s possible to deliver less functional but more engaging map experiences.

Some of the best uses of stylistic maps involve displaying simple information in relation to geography. This could be the locations of an agency’s offices around the world, or an infographic visually demonstrating the relative populations of major countries.
This tutorial walks through creating a basic contemporary map experience using SVGs, CSS3 animations and some crafty layout. The techniques covered in this tutorial can be applied to more complex productions to deliver more engaging experiences.


1. Download the starter kit

Download the starter kit from Web Designer’s dedicated FileSilo pages over at filesilo.co.uk/WebDesigner, which contains all the boilerplate code required to follow and complete this tutorial.

2. Pick a map

Not all world maps are the same, and not all SVGs are equal. A balance between visual detail and source lines of code is required as the SVG needs to be inlined straight into the HTML. Ben Hodgson (@blahpro) has constructed an SVG world map that’s also marked up with ISO 3166 country codes, which can be sourced here: github.com/benhodgson/markedup-svg-worldmap.

3. Style the map

The SVG map can be styled with CSS. The fill and stroke properties are the same as fill and stroke in Adobe Illustrator. The code below selects the node with an id of bg and gives it a transparent fill. This removes the map’s background. The code also darkens the countries and removes their stroke.

svg #bg {
fill: transparent;}
svg [cc] {
fill: #BBBBBB;
stroke: transparent;}

4. SVG scaling problems

Resizing the browser window will reveal that the SVG scales proportionately when the width of the window is shrunk. However, the SVG doesn’t scale when the height of the window is adjusted. This makes it harder to see the geographic relationship of countries on smaller devices.

5. Scale the map

Using new units, view-width and view-height, the code below limits the height and width of the SVG to the browser viewport while maintaining the SVG’s original aspect ratio. The SVG is also perfectly centred using absolute positioning and a CSS transform.

svg {
max-width: 90vw;
max-height: 90vh;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);}

6. Colour in

The benefit of using Ben’s marked up SVG is that styling specific countries becomes as easy as writing CSS selectors. The ISO 3166 standard (specifically 3166-1 alpha 2) assigns each country a two-letter character code. The UK has the code GB.

svg [cc="us"],
svg [cc="ae"],
svg [cc="cn"],
svg [cc="gb"] {
fill: #FF5722;}

7. Create engaging animation

The next step in bringing this world map to life is bringing it into the page in a more dynamic way. This simple fade-in animation can deliver a delightful visual experience when applied in the right way.

@keyframes fadeIn {
from {
opacity: 0;
to {
opacity: 1;}}

8. Work with the animation

There’s nothing fancy going on here. The CSS hides all [cc] nodes with opacity 0. It then applies the fadeIn animation with a fast-slow cubic bezier over two seconds, coming to a stop. There’s also a transition set on the fill property which will be useful later.

svg [cc] {
opacity: 0;
animation: fadeIn
cubic-bezier(0, 0.81, 1, 1)
2s forwards;
transition: fill
cubic-bezier(0, 0.81, 1, 1)

9. Utilise SCSS

Rather than fading all of the countries at once, staggering the animations provides a really nice visual effect. Use SCSS to generate some CSS that delays the animation a little bit more for every single country.

svg [cc] {
@for $i from 1 through 174 {
&:nth-child(#{$i}) {
animation-delay: 0.025 * $i;}

10. Chrome Dev Tools timeline

Pull out Chrome Dev Tools and look at the timeline view with screenshots and paints turned on. This is a relatively complex animation with a lot of elements animating on the page. The performance is good though, as there’s no JS to cause redraws.

11. Toggle button HTML

As the countries are marked up in the SVG, it’s easy to style individual countries. Another feature that can be added is the ability to toggle between states on the map. To begin, add the following button markup to the HTML.

<button class="toggle">Toggle</button>

12. Edit button aesthetics

The styles below create a button that is easily tappable. A slight radius is also added to the edges, to make the button appear slightly less sharp on the page. A transition has been added on the background in preparation for a state change.

button {
border: 1px solid #9C9C9C;
background: transparent;
border-radius: 2px;
color: #9C9C9C;
font-weight: bold;
ext-transform: uppercase;
padding: 10px 15px;
transition: background
cubic-bezier(0, 0.81, 1, 1) 0.5s;} 

13. Toggle positioning

The toggle button is glued to the top left of the screen without writing any code to position it. This is because the only other element, the SVG, is absolutely positioned and therefore taken out of the document flow.

14. Write script

The second state of the map will be styled with CSS, and the button will toggle between the states by adding/removing a class to/from the SVG. This JavaScript finds the elements in the DOM and then binds an event listener to the button click.

button = document.querySelector(
svg = document.querySelector(
'click', clickHandler, false);

15. Work with the script

This function is where the class on the SVG is modified. Using classList, it is possible to add, remove and toggle classes. The toggle function is handy because it’ll add the class if it doesn’t exist and remove it if it does.

function clickHandler(e) {

16. Toggle styles

The toggle styles are set up just like the default fill styles. Countries are targeted through their country codes and a new fill is applied. The only difference here is that these styles will apply only when the SVG has a class of ‘toggle’.

svg.toggle [cc="dz"],
svg.toggle [cc="bi"],
svg.toggle [cc="tz"],
svg.toggle [cc="br"],
svg.toggle [cc="ru"],
svg.toggle [cc="cf"],
svg.toggle [cc="cd"],
svg.toggle [cc="ar"] {
fill: #CDDC39;}

17. Play with it

Always play with the interactive elements of web builds to see if they ‘feel’ right. Here, interacting with the button feels odd because there’s no visual feedback indicating a change in state apart from the map changing.

18. Revisit script

Adding a state to the button can be done in much the same way as the state on the SVG map. Revisiting the clickHandler function from earlier, add a line in that toggles a class on the target of the interaction – in this case the button.

function clickHandler(e) {
requestAnimationFrame(function() {
}); } 

19. Toggle state style

The ‘on’ state of the button doesn’t have to be complicated. In fact, as the main event is the map it is best to keep things simple so the button isn’t distracting. The change in button state should simply signal to the user that something has happened and that’s all.

button.on {
background: rgba(41, 41, 41, 0.54);

20. Review again

Having implemented the new state for the toggle, you should now go back to the page and then have another play with the functionality. Although this is a little detail it really does have an impact on how the interaction with this map feels.

21. Analyse Dev Tools

Open up the Dev Tools and proceed to recording a timeline that captures the process of the ‘toggle’ happening. Zooming into it, it’s now possible to see that everything has been kicked off by a Recalculate Style that was caused by the clickHandler function. From there only paint events happen as the DOM modification has now been completed.


Warning: file_get_contents(http://newsletter-cms.imagine-publishing.co.uk/web/app_dev.php/api/v1/getwidget/gad): failed to open stream: HTTP request failed! HTTP/1.0 500 Internal Server Error in /var/www/html/gadgetdaily.xyz/web/wp-content/themes/gadgetdaily/newsletter-widget/newsletter-header-include.php on line 9