Why Markers & Popups Are Your Map’s Foundation
Markers and popups are the primary interface between your user and your map. They transform a static geographic image into a dynamic tool for discovery and storytelling. Whether you’re highlighting store locations, visualizing data points on a dashboard, or plotting events on a timeline, this combination is the first and most frequent step after displaying the map itself. Mastering it unlocks the core value of any interactive map project.
This guide provides the exact, working code you need to implement this foundational feature across the four most popular JavaScript mapping libraries. We’ll build the same map in each: centering on London and placing a marker with a “Hello, London!” popup. You’ll get parallel examples, understand the syntactic differences, and receive a clear comparison to help you choose the simplest and most suitable API for your needs in 2026.
Setting the Stage: Your Development Environment
Before diving into code, ensure you have a basic HTML file and the necessary API keys. Create a simple HTML file with a div container for your map. For cloud-based services, you’ll need to obtain access tokens.
Getting Your API Keys (Mapbox & Google Maps)
For Mapbox GL JS, you need an access token. Sign up for a free account at Mapbox.com, navigate to your account dashboard, and copy your default public token. This token allows you to load Mapbox styles and use their services within their free monthly limits.
For the Google Maps JavaScript API, you need an API key. Create a project in the Google Cloud Console, enable the “Maps JavaScript API,” and create an API key under “Credentials.” Google requires you to set up billing, but provides a monthly credit ($200 as of 2026) that typically covers initial development and low-traffic use. Restrict your key to your website’s domain for security.
Both services require your site to be served over HTTPS for API calls to work correctly.
Side-by-Side Implementation: Adding a Marker with a Popup
Here is the same use case implemented in four libraries: display a map centered on London ([51.505, -0.09]), add a marker at that location, and attach a popup with the text “Hello, London!” that opens when the marker is clicked.
Leaflet: The Simple & Straightforward Approach
Leaflet uses a straightforward chain of methods. Its API is designed for clarity.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<style>
#map { height: 400px; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = L.map('map').setView([51.505, -0.09], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
L.marker([51.505, -0.09])
.addTo(map)
.bindPopup('Hello, London!');
</script>
</body>
</html>
The marker is added with L.marker(), attached to the map with .addTo(map), and the popup is bound using .bindPopup(). Customizing the marker icon is easy using the L.icon class.
Mapbox GL JS: The Vector-Powered Modern Method
Mapbox GL JS uses WebGL for rendering vector tiles. Its marker is an HTML element placed on top of the WebGL canvas.
<!DOCTYPE html>
<html>
<head>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css" rel="stylesheet" />
<style>
#map { height: 400px; }
</style>
</head>
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; // Replace with your token
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [ -0.09, 51.505 ], // Note: [lng, lat]
zoom: 13
});
const marker = new mapboxgl.Marker()
.setLngLat([ -0.09, 51.505 ])
.setPopup(new mapboxgl.Popup().setHTML('Hello, London!'))
.addTo(map);
</script>
</body>
</html>
Note the coordinate order: Mapbox uses [longitude, latitude]. The marker is created with new mapboxgl.Marker(), its position set with .setLngLat(), and a popup object is attached with .setPopup(). The popup content is set using .setHTML().
MapLibre GL JS: The Open-Source Alternative
MapLibre GL JS is a fork of Mapbox GL JS and maintains API compatibility. You can use it without a Mapbox token, often with free vector tiles from OpenStreetMap.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/maplibre-gl@3.1.0/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@3.1.0/dist/maplibre-gl.css" rel="stylesheet" />
<style>
#map { height: 400px; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json', // Free OSM-based style
center: [ -0.09, 51.505 ],
zoom: 13
});
const marker = new maplibregl.Marker()
.setLngLat([ -0.09, 51.505 ])
.setPopup(new maplibregl.Popup().setHTML('Hello, London!'))
.addTo(map);
</script>
</body>
</html>
The code is nearly identical to Mapbox, only swapping mapboxgl for maplibregl. This makes migration between the two libraries straightforward.
Google Maps JavaScript API: The Familiar Giant
The Google Maps API uses a different paradigm. Markers and info windows (popups) are configured via option objects.
<!DOCTYPE html>
<html>
<head>
<style>
#map { height: 400px; }
</style>
</head>
<body>
<div id="map"></div>
<script>
function initMap() {
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 51.505, lng: -0.09 },
zoom: 13
});
const marker = new google.maps.Marker({
position: { lat: 51.505, lng: -0.09 },
map: map
});
const infowindow = new google.maps.InfoWindow({
content: "Hello, London!"
});
marker.addListener('click', () => {
infowindow.open(map, marker);
});
}
</script>
<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_API_KEY&callback=initMap"></script>
</body>
</html>
The API loads asynchronously via a script tag with a callback. The marker is created with an object defining its position and map. The popup, called an InfoWindow, is separate. You must explicitly add a click listener to the marker to open it.
Head-to-Head Comparison: Which Library Should You Choose?
Seeing the code helps, but choosing requires weighing key project criteria.
| Criteria | Leaflet | Mapbox GL JS | MapLibre GL JS | Google Maps JS API |
|---|---|---|---|---|
| Simplicity & Setup | Very simple. CDN, no API key for basic tiles. | Requires token. Straightforward API. | Similar to Mapbox, no token needed for OSM tiles. | Requires API key & billing setup. Different API pattern. |
| Marker Customization | Highly flexible via L.icon. Can use any image. |
Customizable HTML/DOM element. Less visual variety than Leaflet. | Same as Mapbox. | Limited built-in icon set. Custom icons require image paths. |
| Cost (2026) | Free. Costs only for custom tile hosting. | Free tier: 50k map loads/month, 25k active sessions. Paid plans beyond. | Completely free. Use community or self-hosted tiles. | $200 monthly credit. Cost per map load after credit exhaustion. |
| Performance with Many Markers | Good with plugins for clustering. Can slow with 1000+ raw markers. | Excellent. Built-in GeoJSON clustering and WebGL rendering. | Same as Mapbox. | Good. Native marker optimization, but DOM-based. |
| Documentation & Community | Excellent, mature, vast plugin ecosystem. | Very good, official, commercial support. | Good, growing open-source community. | Excellent, comprehensive, corporate-backed. |
Choose Leaflet if you need a simple, free map with maximum customization and a rich plugin ecosystem for features like marker clustering. It’s the Swiss Army knife for web maps.
Choose Mapbox GL JS or MapLibre GL JS if you require modern vector maps with smooth zooming, built-in performance features like clustering, and advanced styling capabilities. MapLibre is the choice if cost or open-source philosophy is a primary concern. For a deeper dive into building with Mapbox, see our step-by-step Mapbox GL JS tutorial.
Choose the Google Maps JavaScript API if your project mandates the familiar Google Maps look, you need tight integration with other Google services (Places, Directions), or your client/brand requires it.
The Cost Factor: Free Tiers & Pricing in 2026
Cost is a decisive factor. Leaflet and MapLibre are fundamentally free. You may pay for tile hosting or advanced MapLibre styles, but the libraries themselves have no fees.
Mapbox offers a generous free tier (50,000 map loads and 25,000 active user sessions per month as of 2026). Beyond that, pricing is based on map loads and active sessions. Monitor your usage in the Mapbox dashboard.
Google Maps provides a $200 monthly credit. Once exhausted, you pay per map load (typically a few cents per thousand loads). You must enable billing, but costs are negligible for small projects.
Performance & Advanced Scenarios: Handling 1000+ Markers
If your dataset grows, basic marker addition becomes inefficient. Leaflet handles this via plugins like Leaflet.markercluster. Mapbox and MapLibre offer built-in clustering when displaying GeoJSON sources. The Google Maps API has native marker optimization but remains DOM-based. For extreme-scale visualization (10k+ points), consider specialized libraries like deck.gl.
Next Steps: From Simple Markers to Rich Interactive Maps
Adding a marker with a popup is the first step. Your next steps depend on your chosen library.
For Leaflet, explore adding GeoJSON layers, implementing the marker clustering plugin, or integrating search with a geocoding service. For a quick start, our guide on adding an interactive map to your website provides a complete foundation.
For Mapbox/MapLibre, dive into adding GeoJSON sources and layers for complex data visualization, customizing map styles in Studio, or adding 3D terrain.
For Google Maps, integrate the Places API for search or the Directions API for routing.
If you work with React or Next.js, each library has robust integration: react-leaflet for Leaflet, react-map-gl for Mapbox/MapLibre, and @googlemaps/react-wrapper for Google Maps. Choose one library, master its basics, and then expand into the richer world of web mapping.