Introduction
Mapbox GL JS est la bibliothèque JavaScript de référence pour afficher des cartes interactives vectorielles dans le navigateur, propulsée par WebGL pour une performance exceptionnelle même avec des millions de données. En 2026, elle intègre des optimisations natives pour les Progressive Web Apps (PWA), le rendu 3D avancé et l'IA pour la géolocalisation prédictive, la rendant idéale pour les dashboards analytiques, les apps de livraison, les sites e-commerce géolocalisés ou les visualisations IoT.
Ce tutoriel intermediate vous guide de A à Z pour créer une carte professionnelle : initialisation basique, ajout de contrôles de navigation, markers personnalisés avec popups, couches GeoJSON dynamiques et gestion d'événements. Chaque étape fournit du code complet et fonctionnel, copier-collable dans un fichier HTML unique. À la fin, vous maîtriserez les pièges courants et les best practices pour scaler en production. Imaginez comme un GPS fluide dans Google Maps, mais 100% customisable et gratuit pour starter. Prêt à transformer vos données en cartes immersives ? (142 mots)
Prérequis
- Un compte gratuit sur Mapbox pour obtenir un access token public (commence par
pk.). - Connaissances de base en HTML, CSS et JavaScript (ES6+).
- Un éditeur de code comme VS Code avec l'extension Live Server pour servir localement (évite les erreurs CORS).
- Navigateur moderne (Chrome 100+, Firefox 100+).
Structure HTML de base et init carte
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Carte Mapbox GL JS Basique</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoidXNlcm5hbWUiLCJhIjoiY29udGVudCJ9.SECRET_TOKEN'; // Remplacez par votre token public
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [2.3522, 48.8566], // Longitude, latitude Paris
zoom: 10
});
</script>
</body>
</html>Ce code complet crée une page HTML autonome qui charge Mapbox GL JS via CDN et initialise une carte centrée sur Paris avec le style 'streets-v12'. Le conteneur #map occupe tout l'écran grâce au CSS absolu. Remplacez le token placeholder par le vôtre depuis le dashboard Mapbox ; servez via Live Server pour tester instantanément.
Ajout des contrôles de navigation
Les contrôles standards (zoom, rotation, position) améliorent l'UX sans effort. Mapbox fournit des classes prêtes comme NavigationControl et GeolocateControl. On les ajoute après le chargement de la carte via l'événement 'load', évitant les erreurs de timing. Cela rend la carte aussi intuitive qu'un outil pro.
Carte avec contrôles de navigation
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Carte avec Contrôles</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoidXNlcm5hbWUiLCJhIjoiY29udGVudCJ9.SECRET_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [2.3522, 48.8566],
zoom: 10
});
map.on('load', () => {
map.addControl(new mapboxgl.NavigationControl({ showCompass: true }));
map.addControl(new mapboxgl.GeolocateControl({
positionOptions: { enableHighAccuracy: true },
trackUserLocation: true
}));
});
</script>
</body>
</html>Cette version étendue ajoute NavigationControl pour zoom/pan/compas et GeolocateControl pour la géolocalisation GPS. L'événement map.on('load') garantit que la carte est prête. enableHighAccuracy: true booste la précision mobile ; évitez d'ajouter avant 'load' pour prévenir les crashes.
Insertion de markers personnalisés
Les markers surpassent les icônes SVG par leur simplicité et leur drag-and-drop. Utilisez la classe Marker pour des pins custom avec HTML/CSS, parfaits pour points d'intérêt comme magasins ou événements.
Ajout d'un marker personnalisé
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Carte avec Marker</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
.marker-custom {
background: #ff0000;
width: 30px;
height: 30px;
border-radius: 50%;
border: 3px solid white;
cursor: pointer;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoidXNlcm5hbWUiLCJhIjoiY29udGVudCJ9.SECRET_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [2.3522, 48.8566],
zoom: 10
});
map.on('load', () => {
map.addControl(new mapboxgl.NavigationControl());
map.addControl(new mapboxgl.GeolocateControl({ positionOptions: { enableHighAccuracy: true } }));
const marker = new mapboxgl.Marker({ color: 'red', scale: 1.2 })
.setLngLat([2.3522, 48.8566])
.addTo(map);
});
</script>
</body>
</html>Un marker rouge personnalisé est ajouté via new mapboxgl.Marker() à Paris, avec options color et scale. Le CSS .marker-custom peut être appliqué via element: document.createElement('div') pour plus de custom. C'est plus performant que les layers pour peu de points ; drag activé par défaut.
Popups informatives et interactives
Les popups enrichissent les markers avec du contenu dynamique (texte, images, liens). Associez-les à des événements click pour une UX engageante, comme afficher détails d'un événement.
Marker avec popup
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Carte avec Popup</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
.popup-content { padding: 10px; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoidXNlcm5hbWUiLCJhIjoiY29udGVudCJ9.SECRET_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [2.3522, 48.8566],
zoom: 10
});
map.on('load', () => {
map.addControl(new mapboxgl.NavigationControl());
const popup = new mapboxgl.Popup({ offset: 25 }).setText('Tour Eiffel à proximité ! Cliquez pour + d\'infos.');
const marker = new mapboxgl.Marker({ color: 'orange' })
.setLngLat([2.2945, 48.8584])
.setPopup(popup)
.addTo(map);
});
</script>
</body>
</html>La Popup s'attache au marker avec setPopup(), affichant du texte ou HTML via setHTML(). offset: 25 positionne idéalement au-dessus du pin. Utilisez closeButton: false pour persistance ; testez sur mobile où les popups s'adaptent auto.
Couches personnalisées avec GeoJSON
Pour des données massives (routes, bâtiments), ajoutez des sources GeoJSON et layers. C'est vectoriel, zoom-independent, et stylable via Mapbox Studio.
Ajout d'une couche GeoJSON
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Carte avec GeoJSON Layer</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
.geojson-point { background: blue; width: 20px; height: 20px; border-radius: 50%; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoidXNlcm5hbWUiLCJhIjoiY29udGVudCJ9.SECRET_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [2.3522, 48.8566],
zoom: 12
});
map.on('load', () => {
map.addControl(new mapboxgl.NavigationControl());
map.addSource('points-sample', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: { type: 'Point', coordinates: [2.3522, 48.8566] },
properties: { name: 'Point Paris' }
}]
}
});
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points-sample',
paint: { 'circle-radius': 10, 'circle-color': '#007cbf' }
});
});
</script>
</body>
</html>Une source GeoJSON inline alimente un layer 'circle' bleu. addSource puis addLayer ; les properties filtrent via filter. Scalable pour fetch('/data.geojson') ; utilisez Mapbox Studio pour styles complexes sans code.
Gestion des événements et interactions
Rendez la carte vivante avec des listeners : click, mouseenter, zoomend. Parfait pour tooltips dynamiques ou analytics.
Événements sur la carte
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Carte avec Événements</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.css" rel="stylesheet">
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
#info { position: absolute; top: 10px; left: 10px; background: white; padding: 10px; z-index: 1; }
</style>
</head>
<body>
<div id="info">Cliquez sur la carte !</div>
<div id="map"></div>
<script src="https://api.mapbox.com/mapbox-gl-js/v2.17.0/mapbox-gl.js"></script>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoidXNlcm5hbWUiLCJhIjoiY29udGVudCJ9.SECRET_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [2.3522, 48.8566],
zoom: 10
});
map.on('load', () => {
map.addControl(new mapboxgl.NavigationControl());
map.on('click', (e) => {
new mapboxgl.Popup().setLngLat(e.lngLat).setHTML(`<h3>Coords: ${e.lngLat.lat.toFixed(4)}, ${e.lngLat.lng.toFixed(4)}</h3>`).addTo(map);
});
map.on('mouseenter', 'points-layer', () => { map.getCanvas().style.cursor = 'pointer'; });
map.on('mouseleave', 'points-layer', () => { map.getCanvas().style.cursor = ''; });
});
</script>
</body>
</html>Listeners click ouvre une popup aux coords cliquées ; mouseenter/leave change le curseur sur layer. #info div overlay pour feedback. Évitez les handlers globaux sans nettoyage via map.off() pour perf ; idéal pour query features.
Bonnes pratiques
- Sécurisez les tokens : Public (
pk.) pour front-end, secret (sk.) pour backend only. - Limitez les bounds/zoom :
map.setMaxBounds()etzoom: [min, max]pour focus régional. - Lazy-load des données : Fetch GeoJSON après 'load', utilisez
map.queryRenderedFeatures()pour interactions. - Optimisez perf : Clusters pour >1000 points via
supercluster, thèmes sombre/clair switchables. - Accessibilité : Ajoutez
aria-labelaux contrôles, keyboard nav via Mapbox focus API.
Erreurs courantes à éviter
- Pas de serveur local : Ouvre directement HTML → CORS bloque Mapbox CDN/tiles.
- Oubli du token : Carte grise vide ; toujours vérifier console pour 'Invalid access token'.
- Conteneur sans dimensions :
#mapdoit avoir height 100vh ou absolute ; sinon carte invisible. - Ajouter layers avant 'load' : Crashe ; toujours dans
map.on('load', ...). Vérifiezmap.isStyleLoaded().
Pour aller plus loin
- Documentation officielle : Mapbox GL JS Docs.
- Mapbox Studio pour styles custom sans code.
- Intégrez avec React via
react-map-glou Vue. - Découvrez nos formations Learni sur le développement web geospatial pour maîtriser Turf.js et avancées 3D.