mapping with leaflet

21:42 01/04/2025 633 words
contents

what

A tutorial/guide for myself[1] to embed leaflet maps on this site.

how

imports

Leafet.js requires importing (a) some css and (b) some javascript.

I have a file: _includes/partials/leafletHeader.njk, the contents of which looks a lot like:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>

<!-- full screen code -->
<script src="https://cdn.jsdelivr.net/npm/leaflet.fullscreen@3.0.0/Control.FullScreen.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet.fullscreen@3.0.0/Control.FullScreen.css"/>

That is straight from the docs. The first line is the css; the second the js. The third and fourth lines are for importing the full-screen plugin[2].

In my layouts/base.njk template there is the following nunjucks snippet within the <head>:

{% if leaflet %}
    {% include "partials/leafletHeader.njk" %}
{% endif %}

This pipes the contents of leafletHeader.njk into the html <head> if I include leaflet: true in my post's frontmatter.

code for the map

Again, straight from the docs, we need the following js:

var map = L.map('map').setView([0, 0], 1);
const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);

L.control.fullscreen({
    "position": "topleft",
    "title": "Full Screen",
    "titleCancel": "Exit Full Screen",
    "forceSeparateButton": false,
}).addTo(map);

This creates a map centered on Null Island (0.0°N, 0.0°E), with a zoom level of 1; with OSM's default tile & attribution; also added is a full screen toggle. Great.

This code sits in src/js/leafletMap.js. This gets passed through during build. Meaning it gets copied wholesale, rather than injected. See for yourself.

Putting the map on the page requires a container and linking to the js.

<div id="map" style="height:400px"></div>
<script src="/js/leafletMap.js"></script>

adding complexity

Layers and click events and and pop-ups etc... can all be added by linking to additional javascript files. These should all be in js, or a subdirectory within[3] . A another <script> tag is all that is required.

<script src="js/leafletExample/example.js"></script>

where js/leafletExample/example.js looks a bit like:

var geojsonFeature = {
    "type": "Feature",
    "properties": {
        "name": "Coors Field",
        "amenity": "Baseball Stadium",
        "popupContent": "This is where the Rockies play!"
    },
    "geometry": {
        "type": "Point",
        "coordinates": [-104.99404, 39.75621]
    }
};

L.geoJSON(geojsonFeature).addTo(map);

all together now

At the risk of being overly verbose: the sum total of code required in a given markdown file is:

  1. some frontmatter
leaflet: true
  1. a line of html
<div id="map" style="height:400px"></div>
  1. a pair (or more, as required...) of script tags
<script src="/js/leafletMap.js"></script>
<script src="js/leafletExample/example.js"></script

and for the sake of completeness, here is what the my directories look like, including all the relevant files for this post (leaflet.md)

├── src
│   ├── blog
│   │   ├── 2025
│   │   │   └── 04
│   │   │       └── leaflet.md
│   │   └── blog.json
│   ├── _includes
│   │   ├── layouts
│   │   │   ├── base.njk
│   │   │   ├── blog.njk
│   │   └── partials
│   │       ├── leafletHeader.njk
│   ├── js
│   │   ├── leafletExample
│   │   │   └── example.js
│   │   ├── leafletMap.js

the result

references

footnotes


  1. and who knows, maybe you? ↩︎

  2. which I might move to another .njk partial at some point ↩︎

  3. maybe this helps keeps me a bit organised ↩︎


#maps #11ty #js #leaflet