Embedding Leaflet.js Maps in Reveal.js Presentations
04 Apr 2016I 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: '© <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!