LEHNHOF.NET

Creating maps in HTML and CSS

Abstract: When it comes to highlighting certain areas of a country, use map fonts instead of SVGs whenever possible. If you don’t have a map font, build one.

Imagine you wanted to highlight certain areas of a country for datavis reasons without using any Flash or flashy stuff. You only speak HTML and CSS. You want the map to work in all browsers and all resolutions. You want lossless scalability and you also want to provide mobile users with a fast and pleasant UX. And you don’t want to pay someone to do the job.

There are different ways to display cartographic data in your browser using only HTML and CSS, and embedding a JPG is obviously not an option. In this post, I shall discuss two methods, both of which use an SVG file of the desired area. The first one is to tinker with the XML source of a public domain SVG, the second one is to create a map font out of such. Each method caters to different needs and has different disadvantages.

Highlighting areas in a SVG

In SVG files, graphical data is described in a human-readable XML format. If you want to highlight a certain state of a country, you could just take a random SVG, open the file in your favourite text editor, skim for the XML class of the respective region and replace the color manually. Sounds easy and might just work, provided you have an exemplary SVG markup consisting of CSS classes for each country:1

SVG map of Europe, with Germany being highlighted


.de {fill:#A75050;}

However, this is not always the case. On the one hand, the markup might not be as useful as it could be: missing CSS classes and unreasonable spacing make editing harder (in this case, try the interactivity functions of Inkscape). On the other hand, the different areas of your new found map can be made up almost entirely of polylines instead of polygons, probably for compression reasons. And while sparse markup simply makes editing take longer, a space-saving architecture can make a map completely uneditable in the first place. See the following example:2

Broken SVG map of Germany


<polyline ... fill="#A75555" ... />

If you got hold of a good map, check the file size first. A 1024kb vector file might look beautiful, but it can make dusty, old machines writhe in pain. Images of a moderate size do produce a fine UX and nobody’s going to pan you if the border is a few miles off. SVGZ files might be an alternative, since they offer a good compression ratio.

For the record: Instead of simply displaying an SVG via the <img> tag, you might as well embed it. A major advantage of embedded SVGs is that you can add fancy stuff like hover effects or links outside of the image. But technically, you would leave the whole HTML and CSS only thing then. Just to give you an impression: In the following example, clicking the highlighted area in the West will lead you to the Wikipedia article on North Rhine-Westphalia:3


<a
id="a27"
xlink:href="http://en.wikipedia.org/wiki/North_Rhine-Westphalia">
<path ... style="fill:#A75555; ... id="NRW" />
</a>

Creating map fonts

There is a second way to do this: Ben Markowitz recently came up with Stately, a beautiful webfont of the US containing separate glyphs for each state. The basic idea is that you have any state or region of a country saved as a separate SVG via Inkscape, including the transparent rest of the map. The individual SVGs are then converted into glyphs of a webfont – see Ben’s tutorial for the details.

All of these glyphs are then written as letters inside a HTML document and stacked on top of one another via CSS positioning. Imagine drawing all states on individual overhead transparencies to get the idea. The exact same thing happens in professional image processing programs, where you combine multiple layers of graphical information to a final image.

The resulting map is fully scalable, although you cannot interact with lower layers (which reads: no fancy stuff allowed). But since each layer has its own CSS class, it can of course be coloured separately with a single line of code and no SVG sleuthing at all. I allowed myself to create a font of Germany and visualise two sets of data – the German states demanding college tuition fees (two) and those demanding a fee for officially leaving the church (all but two).4 Notice that the .ttf file is only 23kb and includes even the smallest North Sea islands:

College tuition fees

  • a
  • b
  • c
  • d
  • e
  • f
  • g
  • h
  • i
  • j
  • k
  • l
  • m
  • n
  • o
  • p


#college {
color: #b0b0b0;
}
#college .bavaria,
#college .lower_saxony{
color: #A75555;
}

Fees for leaving the church

  • a
  • b
  • c
  • d
  • e
  • f
  • g
  • h
  • i
  • j
  • k
  • l
  • m
  • n
  • o
  • p


#church {
color: #A75555;
}
#church .berlin,
#church .brandenburg{
color: #b0b0b0;
}

Pros & cons, framework in development

So what is our takeaway? You might edit an SVG and display it via <img> in any browser. You might also embed it, although embedding remains a problem for earlier IE and Android versions (see caniuse.com). But styling the whole thing within a reasonable amount of time can become a problem, and SVGs can be quite large. Ultimately, it is not an economical way to do the job, because you have to edit the file again as soon as you want to visualise different data.

The second approach works in any browser capable of displaying CSS3 (see caniuse.com) and allows you to apply any style you want – once the desired font has been generated. You have to work with the SVG anyway, so why not create a webfont and share it? It is a convenient way of highlighting selected areas and styling your map. It is also beautiful and hacky and small and fast. A few numbers on the webfont for Germany:

  • SVG: 220kb
  • SVGZ: 86kb
  • TTF: 23kb

So where’s the global open source map font framework? It is right there in my Github repo. I made a few enhancements to Ben’s original Stately files so you can add your own country easily. I am still figuring things out on GitHub and I hope my push conforms to etiquette.

P.S.: I may also have found an easier way to create the glyphs without saving all SVGs separately – leave a comment if you are interested in an Inkscape tutorial.

(1) Source: Wikimedia Commons (File: September 12, 2012, 20:47)
(2) Source: Wikimedia Commons (File: October 2, 2012, 12:32)
(3) Source: Wikimedia Commons (File: August 27, 2011, 03:23). Fun fact: The German Wikipedia community projects HTML-3.2.-style image maps on SVGs and prevents them from scaling via CSS (see source code, lines 80-114).
(4) Derivative work of Wikimedia Commons file (October 2, 2012, 12:32)

Comment on this article