Leaflet.js — Complete Open-Source Interactive Maps Guide
Leaflet.js is the leading open-source JavaScript library for interactive maps — lightweight (~42KB gzipped), mobile-friendly, and free to use without API keys or licensing fees.
What You’ll Learn
How to set up Leaflet maps with OpenStreetMap tiles, add markers and popups, draw circles and polygons, work with GeoJSON data, implement custom controls, and choose plugins for clustering, heatmaps, and routing.
Why Leaflet.js Matters
Leaflet is the go-to mapping library when you need free, self-hosted, or offline maps without vendor lock-in. It powers thousands of open-source projects, government data portals, and privacy-focused applications. DodaTech uses Leaflet in Doda Browser’s privacy-safe location features — no Google API keys, no tracking, just open tiles.
Security note: Understanding Leafletjs helps build more secure applications — a core principle at DodaTech, where tools like Durga Antivirus Pro and Doda Browser rely on solid implementation practices.
graph LR
A[JavaScript & HTML] --> B[Leaflet Setup]
B --> C[Tile Layers]
C --> D[Markers & Popups]
D --> E[GeoJSON]
E --> F[Plugins & Custom Controls]
style B fill:#4f46e5,color:#fff
Core Concepts Explained
Think of Leaflet as a blank map canvas that you fully control. Unlike Google Maps, you choose where your map tiles come from (OpenStreetMap, Mapbox, your own tileserver), and there are no usage limits, no billing, and no API keys. The library is tiny but extensible — you only add what you need.
Basic Setup
<link rel="stylesheet" href="https://unpkg.com/leaflet@1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1/dist/leaflet.js"></script>
<div id="map" style="height: 400px;"></div>Leaflet requires a CSS file (for map controls and tile styling) and a JS file. The map needs a container <div> with a defined height — without a height, you’ll see nothing.
const map = L.map("map").setView([51.505, -0.09], 13);L.map("map") creates a map bound to the container div. setView([latitude, longitude], zoom) positions the map and sets the zoom level. The coordinate format is [lat, lng] — note that latitude comes first (different from Google Maps which uses {lat, lng}).
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "© OpenStreetMap contributors"
}).addTo(map);Tile layers are the visual background of your map. The URL template {s}.tile.openstreetmap.org/{z}/{x}/{y}.png tells Leaflet where to fetch square image tiles. {z} is zoom level, {x}/{y} are tile coordinates. OpenStreetMap tiles are free but require attribution — the attribution string ensures legal compliance.
Markers and Popups
L.marker([51.5, -0.09])
.addTo(map)
.bindPopup("Hello from London!");L.marker([lat, lng]) creates a pin marker. .addTo(map) attaches it to our map. .bindPopup("Hello from London!") creates a popup that opens when the marker is clicked.
Circles
L.circle([51.508, -0.11], {
color: "red",
fillColor: "#f03",
fillOpacity: 0.5,
radius: 500
}).addTo(map).bindPopup("I am a circle");Circles are useful for showing radius coverage, proximity zones, or heat areas. The options control: color (stroke), fillColor (interior), fillOpacity (transparency), and radius (in meters).
GeoJSON
L.geoJSON(geojsonFeature, {
style: { color: "blue" },
onEachFeature: (feature, layer) => {
layer.bindPopup(feature.properties.name);
}
}).addTo(map);GeoJSON is the standard format for geographic data on the web. You can load polygons (countries, districts), lines (routes), and points (locations). The style function sets visual properties, and onEachFeature allows you to attach popups or event handlers per feature.
Custom Controls
const searchControl = L.Control.extend({
onAdd: function(map) {
const div = L.DomUtil.create("div", "leaflet-bar leaflet-control");
div.innerHTML = '<input type="text" placeholder="Search location..." style="padding: 4px 8px; width: 200px;">';
return div;
}
});
map.addControl(new searchControl({ position: "topright" }));Leaflet lets you build custom controls that integrate seamlessly with the map’s existing UI. The L.Control.extend pattern creates a new control class. onAdd is called when the control is added to the map, and it returns the DOM element that becomes part of the map’s control pane.
Plugin Ecosystem
Leaflet’s strength is its plugin ecosystem. Key plugins:
- MarkerCluster: Groups nearby markers into clusters for better performance with thousands of points
- Leaflet.heat: Renders heatmaps from point data (crime density, traffic hotspots)
- Leaflet Routing Machine: Turn-by-turn directions using OSRM
- Leaflet Draw: Draw shapes directly on the map for geofencing
- Leaflet Fullscreen: Fullscreen map control for immersive experiences
- Leaflet ExtraMarkers: Custom styled markers with colors, numbers, and Font Awesome icons
Common Mistakes
- Not setting a container height: The map container must have an explicit CSS height —
height: 0(default div) renders an invisible map - Confusing Leaflet coordinates with Google Maps: Leaflet uses
[lat, lng]arrays; Google Maps uses{lat, lng}objects — mixing them causes misplaced markers - Missing tile attribution: OpenStreetMap requires attribution text in the map. Without it, you risk legal issues and tile access revocation
- Loading tiles over HTTPS from HTTP tileserver: Mixed content warnings block tile loading on secure pages — always use HTTPS tile URLs
- Not handling tile loading errors: When tiles fail to load (server down, rate limit), the map shows empty gray areas — provide a fallback tile layer
Practice Questions
Q1: What is the difference between L.marker() and L.circle()?
A1: L.marker() creates a pin icon at a point. L.circle() draws a geometric circle with defined radius, stroke, and fill — useful for proximity zones.
Q2: How does Leaflet handle map tiles differently from Google Maps? A2: Leaflet lets you choose your tile provider (OpenStreetMap, Mapbox, self-hosted). Google Maps uses its own proprietary tiles and requires an API key.
Q3: Why is GeoJSON important for Leaflet applications? A3: GeoJSON is the standard interchange format for geographic data. It allows loading polygons, lines, and points with associated properties — essential for mapping boundaries, routes, and locations.
Challenge: Build a hiking trail map that loads a GeoJSON file of trail routes, styles them by difficulty (green=easy, blue=moderate, red=hard), shows elevation profiles in popups, and includes a tile layer switcher (OpenStreetMap, satellite, terrain).
FAQ
Try It Yourself
What’s Next
| Topic | Description |
|---|---|
| Google Maps JavaScript API | Compare with a commercial, feature-rich mapping alternative |
| JavaScript | Master async patterns for loading and processing GeoJSON data |
| HTML | Structure responsive map layouts |
CSS is essential for customizing map controls and popups. Explore JSON for GeoJSON data, and D3.js for combining map projections with data visualizations.
What’s Next
Congratulations on completing this Leafletjs tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro