Mapping the digital world, one bit at a time.

Tutorials

How to Build a Simple Web Map with Leaflet and Open Data

How to Build a Simple Web Map with Leaflet and Open Data

An interactive web map is one of the most satisfying things you can build on the web. A few dozen lines of HTML, CSS and JavaScript will get you a pannable, zoomable map with pins that open little windows of information, and you will not need a paid API key, a cloud account or a GIS qualification to get there. Leaflet is the library most people reach for: it is small, readable, and plays nicely with open data. What follows takes you from an empty file to a working map with markers, popups and real points loaded from a dataset.

What you actually need

Less than you might expect. A text editor, a browser, and somewhere to serve a couple of files. Leaflet is loaded from a content delivery network with a single script tag, so there is nothing to install and no build step to configure.

You also need open data. For the walkthrough, any file with latitude and longitude columns will do. If you want something realistic, look at your local council's open data portal, data.gov.uk, or OpenStreetMap extracts; Natural Earth is useful for country and coastline shapes.

One practical tip before you start: browsers block fetch requests made from a file opened directly off your hard drive. For the first few steps that will not matter, but the moment you load a GeoJSON file you will want a local web server. If you have Python installed, run python -m http.server in your project folder and visit localhost in your browser instead of double-clicking the HTML.

Build the page shell first

Start with a single HTML file. Include the Leaflet stylesheet in the head, then a container element with an id, then the Leaflet script before your own code so the library exists when your script runs.

The container needs an explicit height. This is the mistake nearly everyone makes once: a div with no height collapses to nothing, and you get a blank page with a working map hiding inside it. A rule such as #map { height: 500px; } fixes it immediately. Give the map a width of 100% and let the page handle the rest.

Add an open tile layer

Tiles are the square images that make up the background. Initialise the map, set a starting view, then attach a tile layer:

var map = L.map('map').setView([51.5074, -0.1278], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: 'Map data © OpenStreetMap contributors',
  maxZoom: 19
}).addTo(map);

Two things matter here. The attribution line is not optional — OpenStreetMap's data is open, but credit is part of the deal, and you should keep the attribution control visible rather than hiding it under a custom button. And the standard OpenStreetMap tile servers are run on donations, with a usage policy that rules out heavy traffic. For a personal project or a low-traffic page you are fine. If your map starts getting serious visits, move to a hosted tile service or generate your own.

Alternatives worth knowing: OpenTopoMap for hill shading and contours, the Carto light and dark basemaps for data-heavy overlays, and Ordnance Survey open data if you need detailed British context. The National Library of Scotland publishes historic mapping tiles that are excellent for local history projects.

Markers and popups

A marker is one line, and a popup is another attached to it:

L.marker([53.4808, -2.2426]).addTo(map)
  .bindPopup('<strong>Manchester</strong><br>Sample point');

Coordinates are always latitude first, longitude second — the reverse of how most people say them aloud, and a reliable source of accidentally flipped pins. Popup content is treated as HTML, so you can style it, but never drop raw text from an untrusted source straight in. Header names from a public spreadsheet count as untrusted. If in doubt, escape the characters that could break your markup.

For more than a handful of points, swap markers for circle markers: they are lighter to draw and read better when the map is crowded. Beyond a few hundred points, add marker clustering so the map stays legible as you zoom out.

Bringing in open data

The pattern is the same whether your data comes as GeoJSON, CSV or a web service. Work through it in this order:

  1. Find the dataset and check its licence allows reuse with attribution.
  2. Trim it to the columns you need — latitude, longitude, a name, and one or two details worth showing.
  3. Convert it to GeoJSON, or keep the CSV and write a small loop that creates a marker per row.
  4. Fetch the file in your script and build a layer from it, binding a popup inside an onEachFeature function.
  5. Call map.fitBounds(layer.getBounds()) so the view frames your data instead of guessing a centre.

Watch the coordinate system. Most open data is in WGS84 decimal degrees, which is exactly what Leaflet expects. Some British datasets — council planning records especially — arrive as Eastings and Northings on the British National Grid. Those numbers look nothing like latitudes, and the pins will land in the wrong hemisphere if you skip the conversion. A projection library such as proj4js handles it.

Small touches that make a map usable

  • Set minZoom and maxBounds so users cannot pan off into empty ocean.
  • Tone the tiles down with a CSS filter if your data needs to stand out against a busy basemap.
  • Test with one hand on a phone. Tap targets smaller than about 40 pixels are frustrating.
  • Give the map container a sensible height on small screens — a fixed 500 pixels can fill an entire phone viewport.
  • Check that popups close properly and that the map still responds if a data request fails. A failed fetch should leave a usable map, not a blank one.

Publishing and keeping it healthy

Once it works locally, drag the folder into a static host: GitHub Pages, Netlify and Cloudflare Pages all serve plain files with HTTPS for free, which matters because browsers restrict some features on insecure origins. Keep your GeoJSON lean — a tool like mapshaper will simplify geometry and strip unused properties, often shrinking a file that took several seconds to load down to something instant. Then revisit your tile source before you share the link widely, and make sure the attribution still names every data provider you have used.

Where to take it next

You now have the whole foundation: tiles, a layer, points and popups. Most of what people admire in polished web maps is built from those same four parts. Try filtering markers with a checkbox list, colouring circle markers by a category in the data, or linking two maps so they pan together. If you want the next real jump, learn GeoJSON properly — once you can read and write it by hand, nearly every open dataset becomes a map waiting to happen.

Photo: Antoni Shkraba / Pexels

Related Posts

A Beginner's Guide to UK Postcodes for Geospatial Analysis

Geodata

A Beginner's Guide to UK Postcodes for Geospatial Analysis

A practical introduction to UK postcode structure, geocoding options and aggregation choices for mapping location...

Mapping Public Rights of Way in England and Wales

Maps

Mapping Public Rights of Way in England and Wales

A practical guide to England and Wales' definitive maps, CRoW access land and the open data sources you can use to...