Per
Liedman

Embedding Leaflet.js Maps in Reveal.js Presentations

I love reveal.js, and I’ve made a couple of presentations with it over the last couple of months. All of them have included live code examples with Leaflet.js maps in them. Since it wasn’t entirely obvious how to make that work, I thought documenting how to go about it here was a good idea.

Prerequisites

Like any page that uses Leaflet, you’re going to have to load Leaflet’s stylesheet and the JavaScript. Just add them to your reveal.js HTML file.

I added the leaflet.css stylesheet to load after reveal.css and the theme stylesheet, etc.

I include the leaflet.js (or perhaps leaflet-src.js, if you plan on debugging something) right after reveal.js; it might be better to load it through dependencies, but I’m always in too much of a hurry to bother trying that out. Loading it with a normal script tag will work fine.

Adding a map

To create a map on a slide, just create a div tag with an id of your choice on any slide, just like you would when creating any Leaflet map. Make sure to add some styling to that div, so it actually gets a size (this applies to any Leaflet container, also outside reveal.js); personally I use a CSS class called map to give it appropriate size. Also, create another script tag that includes the script that initializes your map. This simple “hello world” map should (sort of, see next paragraph) work, given that you add a <div id="map-test" class="map"></div> to one of your slides:

var map = L.map('map-test').setView([0, 0], 2);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

Now, have a look at the result.

Ok, yeah, so that’s why decided to write this post. Out of the box, a lot of reveal.js’ styling interferes with Leaflet’s styling, making the map unusable.

The problem is that some of reveal.js’ styles for img tags and some other things have higher specificity than Leaflet’s, which makes them override Leaflet.

Overriding reveal.js’ builtin styling for maps

What I’ve done to avoid this, is to re-add a copy of Leaflet’s CSS rules with the extra selectors .reveal .leaflet-container as prefix, which gives these rules higher specificity than reveal.js’ rules. This means the map will use the Leaflet styling, while other elements, outside maps, will still use reveal.js’ style.

Here are the style overrides I use:

Ok, nice? Yes. But do you notice something still a bit off?

At least on some screens, your Leaflet map will appear blurry, and even worse: popups and other graphic elements might appear in the wrong place on your map.

Un-zooming reveal.js’ zooming

This is because reveal.js has a trick where it scales or zooms the entire view, to make it fit on your screen, and make it less dependant on the exact resolution your presentation runs on. For normal presentations, this is a fantastic function, but as mentioned above it becomes trouble for Leaflet maps.

To address this, I’ve added a hook to Leaflet’s map constructor, making sure its container is zoomed out just enough to counter reveal.js zoom in, so that the combined scale factor is exactly 1. This makes map tiles look crisp again, and makes sure screen coordinates and lat/lngs match up as expected.

This is it! With this code, I have happily included maps in my last two presentation: Let’s Learn Leaflet.js and Making Tiled Maps Come Alive: Leaflet Underneath.

Hope this helps your presentations as well!


Comments or feedback to this post?

I'm @liedman on Twitter or send an e-mail to per@liedman.net.