Skip to main content

Add custom markers in Mapbox GL JS

Prerequisite
Familiarity with front-end development concepts, a Mapbox account, and an IDE/Code Editor.

In this tutorial, you will learn how to build an interactive web map that adds custom markers at specified locations using Mapbox GL JS. You will also add informative popups when a user clicks one of these markers.

Your final map will look like this:

Prerequisites

To follow along with this guide you'll need:

  • Front-end familiarity: Some familiarity with front-end development (HTML, CSS, and JavaScript)
  • Mapbox account: Sign up or log into a free account at account.mapbox.com.
  • IDE / Code editor: A program like Visual Studio or Sublime Text to edit your HTML file.

We also recommend you view the related video tutorial for additional guidance.

Accessing Sample Code

If you wish to copy the code sample in its entirety instead of following along with the tutorial, view the code snippet at the bottom of the page.

Step 1: Create an HTML file

Create a new HTML file and name it index.html.

Step 2: Initialize your map

Initialize your map by adding code to your index.html file.

  1. Open your index.html file in your code editor.
  2. Copy and paste the code below into your file.
  3. Once pasted, check that mapboxgl.accessToken is assigned to your public access token. This value should start with pk.
    • If you see YOUR_MAPBOX_ACCESS_TOKEN, log into your account and copy the code snippet again. Your token is automatically added to your code snippet when you're logged in.
  4. Open your index.html file in a browser and you should be able to see the default mapbox globe.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Add custom markers in Mapbox GL JS</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Open+Sans"
rel="stylesheet"
/>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.js"></script>
<link
href="https://api.tiles.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.css"
rel="stylesheet"
/>
<style>
body {
margin: 0;
padding: 0;
}

#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}

<!--code from step 5-3 will go here!-->

<!--code from step 7 will go here!-->
</style>
</head>
<body>
<div id="map"></div>

<script>
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';

//code from step 3 will go here

const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v11',
center: [-96, 37.8],
zoom: 3
});

//code from step 4 will go here

</script>
</body>
</html>
Mapbox GL JS `Map` options

As you can see above, the Mapbox GL JS Map is instantiated with several options defined:

  • container: the id of the <div> element on the page where the map should live. In this case, the id for the <div> is 'map'.
  • style: the style URL for the map style. In this case, use the Mapbox Light map which has the style URL mapbox://styles/mapbox/light-11.
  • center: the initial centerpoint of the map in [longitude, latitude] format.
  • zoom: the initial zoom level of the map.

Step 3: Load GeoJSON data

Next let's determine where your markers will appear on the map by creating a GeoJSON object.

GeoJSON is a web-friendly spatial data format that can store geometries such as Points, Linestrings, and Polygons, and their associated data properties. We can use Point data in GeoJSON format to determine where our markers will be placed, by following these steps:

  1. Find where it says // code from step 3 will go here in your code.
  2. Copy and paste the code snippet below and replace the comment line.
const geojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-77.032, 38.913]
},
properties: {
title: 'Mapbox',
description: 'Washington, D.C.'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.414, 37.776]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}
]
};
Large GeoJSON files

If you have a lot of GeoJSON data, you may want to load it as an external file rather than adding it inline. You can do so by linking to its URL, if it's hosted remotely, or by using fetch to load locally or from a third-party API.

Step 4: Add default markers to the map

Let's create and attach a marker at each point in our GeoJSON data. We'll start by using the default marker and customize our markers in Step 5.

To do so follow these steps:

  1. To add in your markers, copy and paste the following code and replace where it says //code from step 4 will go here.
    • This is located within your script, after the end of your Map object instantiation and before the </script> tag.
  2. Save your index.html file and refresh your browser to view your two default markers on the east and west coasts of the map.
// add markers to map
for (const feature of geojson.features) {

// code from step 5-1 will go here

// make a marker for each feature and add to the map
new mapboxgl.Marker().setLngLat(feature.geometry.coordinates).addTo(map); // Replace this line with code from step 5-2

//code from step 6 will go here
}

Your default markers should appear like they do in the image below:

Step 5: Customize and style your markers

Now that we've spawned two default markers, we can add custom HTML elements to control their appearances.

Step 5-1: Create an empty div for each point.

Let's make an HTML DOM element for each Marker by passing an empty div into the marker's constructor. This will attach each div to a location listed in your GeoJSON data.

Add this code segment where it says // code from step 5-1 will go here.

// create a HTML element for each feature
const el = document.createElement('div');
el.className = 'marker';

Step 5-2: Pass the empty div into the marker's constructor.

Next replace the code on the line that ends with // Replace this line with code from step 5-2 with the following segment of code:

new mapboxgl.Marker(el).setLngLat(feature.geometry.coordinates).addTo(map);

This will pass the empty div (stored in the variable el) into the constructor.

Step 5-3: Add CSS to style the markers.

You'll need to specify the style of the marker, so the div renders something at each point. This will add an image to each of the markers and adjust them to a uniform size of 50 by 50 pixels and change the image of the cursor when it's over the element so your users know they can interact with it.

To do this, copy and paste the CSS code below in the style section of the header, where it says <!--code from step 5-3 will go here!-->.

.marker {
background-image: url('https://docs.mapbox.com/help/demos/custom-markers-gl-js/mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}

Step 6: Attach popups to markers

Let's add the JavaScript needed to add the popups. These will contain information about each point and display the popup when a marker is clicked:

  1. Copy and paste the right above the end </script> tag, where it says //code from step 6 will go here.
    • In this example, we're displaying the title and description properties from the GeoJSON data, but you are able to customize what data is stored and shown as you see fit.
  2. Save your file and refresh your browser.
  3. Click on the markers and to view the popups displays.
new mapboxgl.Marker(el)
.setLngLat(feature.geometry.coordinates)
.setPopup(
new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML(
`<h3>${feature.properties.title}</h3><p>${feature.properties.description}</p>`
)
)
.addTo(map);
Offset your popups

Notice that you've added an offset value when you declare popups using the mapboxgl.Popup method. This makes sure your popups are positioned near your markers and not directly on top of them.

Step 7: Add a style for marker using CSS

Now lastly, let's style our popups to make them present more neatly, by completing the following:

Copy and paste the CSS code below and paste the code inside your style tag below the .marker declaration on line 38, where it says <!--code from step 7 will go here!-->.

.mapboxgl-popup {
max-width: 200px;
}

.mapboxgl-popup-content {
text-align: center;
font-family: 'Open Sans', sans-serif;
}

Finished Product

You've made an interactive marker map with custom data and styling using Mapbox GL JS.

Finished Interactive Map

Finished Code Snippet

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Demo: Add custom markers in Mapbox GL JS</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
href="https://fonts.googleapis.com/css?family=Open+Sans"
rel="stylesheet"
/>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.js"></script>
<link
href="https://api.tiles.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.css"
rel="stylesheet"
/>
<style>
body {
margin: 0;
padding: 0;
}

#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}

.marker {
background-image: url('https://docs.mapbox.com/help/demos/custom-markers-gl-js/mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}

.mapboxgl-popup {
max-width: 200px;
}

.mapboxgl-popup-content {
text-align: center;
font-family: 'Open Sans', sans-serif;
}
</style>
</head>
<body>
<div id="map"></div>

<script>
mapboxgl.accessToken = '{{MAPBOX_ACCESS_TOKEN}}';

const geojson = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.032, 38.913]
},
'properties': {
'title': 'Mapbox',
'description': 'Washington, D.C.'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-122.414, 37.776]
},
'properties': {
'title': 'Mapbox',
'description': 'San Francisco, California'
}
}
]
};

const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v11',
center: [-96, 37.8],
zoom: 3
});

// add markers to map
for (const feature of geojson.features) {
// create a HTML element for each feature
const el = document.createElement('div');
el.className = 'marker';

// make a marker for each feature and add it to the map
new mapboxgl.Marker(el)
.setLngLat(feature.geometry.coordinates)
.setPopup(
new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML(
`<h3>${feature.properties.title}</h3><p>${feature.properties.description}</p>`
)
)
.addTo(map);
}
</script>
</body>
</html>

Next steps

Now that you've created a project using Mapbox GL JS, we recommend checking out our other tutorials to extend your web app:

Explore our Mapbox GL JS examples for more ideas on how to extend your project and code to get you started.

Was this page helpful?