Work with markers in Mapbox.js

In this guide, we’ll show how to add markers, customize them, and make them interactive with Mapbox.js. Think of this guide as a curated stroll through all that’s possible with markers.

Before you continue, check out the Extending with Mapbox.js guide to learn the basics of Mapbox.js.

Getting started

For this guide you’ll need:

  • Your API access token. If you’re logged in, we automatically added your token to the examples in this guide. You can also find your access token on your account page.
  • A map ID. You swap out any of your project or style map IDs, but we’ll be using Mapbox map IDs.

To better understand each example, click “View source” to browse the code. You can also copy the full source code to use on your own projects. We adapted many of these demos from Mapbox.js examples.

Adding markers

You can add markers to map with the Editor, Leaflet, and GeoJSON. In this section, we’ll explore each method.

With Editor

With our online Editor, you can drag and drop markers, lines, and polygons on a map. We even have a guide to help you do it. After you’ve saved your project, you can use that map ID to load your map and its data. In this example, we added markers to the map in Editor.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map-editor' class='map'></div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapEditor = L.mapbox.map('map-editor', 'mapbox.o11ce7if')
  .setView([37.8, -96], 4);
mapEditor.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

With Leaflet

You can add a simple marker to your map with L.marker. In the example below, we added a marker to the map just by knowing its coordinates. This technique is great for when you have only a few markers to add.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map-leaflet' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapLeaflet = L.mapbox.map('map-leaflet', 'mapbox.light')
  .setView([37.8, -96], 4);

L.marker([38.913184, -77.031952]).addTo(mapLeaflet);
L.marker([37.775408, -122.413682]).addTo(mapLeaflet);

mapLeaflet.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

With GeoJSON

You can save your marker coordinates as GeoJSON and then load it on a map with Mapbox.js. In this example, we added coordinates to the Mapbox DC and SF offices in GeoJSON. GeoJSON is great for organizing features, especially when working with larger data files.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map_geo' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    }
  }
];

var mapGeo = L.mapbox.map('map_geo', 'mapbox.light')
  .setView([37.8, -96], 4);

var myLayer = L.mapbox.featureLayer().setGeoJSON(geojson).addTo(mapGeo);
mapGeo.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

You can also load GeoJSON as an external file, hosted locally or on Github. In the next section, we’ll show you how to style GeoJSON markers with simplestyle specification (spec).

Styling markers

To style a marker you can add simplestyle to your GeoJSON, you can load a custom image, or you can create your own markers with HTML and CSS. Let’s take a look at all the different styling options.

With simplestyle

Simplestyle spec is a styling convention for GeoJSON. This means that you can add specific keys and values to each marker to add or change its color, symbol, and size.

Here are all the possible style keys and values:

Key Value Example
"marker-color" Any hex value
Example: "#3bb2d0"
"marker-symbol" Any Maki icon name, an integer or a lowercase letter
Example: "1"
"marker-size" small, medium, large
Example: "large"

In this example, we took the GeoJSON from the previous section and added simplestyle. View the source to see how the marker styles are added to each feature.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map_simple' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      'marker-color': '#3ca0d3',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    },
    properties: {
      'marker-color': '#63b6e5',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  }
];

var mapSimple = L.mapbox.map('map_simple', 'mapbox.light')
  .setView([37.8, -96], 4);
var myLayer = L.mapbox.featureLayer().setGeoJSON(geojson).addTo(mapSimple);
mapSimple.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

With an image

You can define a custom marker image in your GeoJSON by adding an icon object to each feature. In this example, we used L.icon to set the features found in the icon object.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map-one' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapOne = L.mapbox.map('map-one', 'mapbox.light')
  .setView([37.8, -96], 4);
var myLayer = L.mapbox.featureLayer().addTo(mapOne);

var geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      icon: {
        iconUrl: 'https://www.mapbox.com/mapbox.js/assets/images/astronaut1.png',
        iconSize: [50, 50], // size of the icon
        iconAnchor: [25, 25], // point of the icon which will correspond to marker's location
        popupAnchor: [0, -25], // point from which the popup should open relative to the iconAnchor
        className: 'dot'
      }
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    },
    properties: {
      icon: {
        iconUrl: 'https://www.mapbox.com/mapbox.js/assets/images/astronaut2.png',
        iconSize: [50, 50], // size of the icon
        iconAnchor: [25, 25], // point of the icon which will correspond to marker's location
        popupAnchor: [0, -25], // point from which the popup should open relative to the iconAnchor
        className: 'dot'
      }
    }
  }
];
myLayer.on('layeradd', function(e) {
  var marker = e.layer,
    feature = marker.feature;
  marker.setIcon(L.icon(feature.properties.icon));
});
myLayer.setGeoJSON(geojson);
mapOne.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

With HTML and CSS

You can replace the standard marker with a <div>, assign it a class, and then style it with CSS with divIcon. In this example, we followed similar patterns as adding a marker image, but instead we assigned a class name to the features and then added CSS to style it.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<style>
.my-icon {
  border-radius: 100%;
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  color: white;
}

.icon-dc {
  background: #3ca0d3;
}

.icon-sf {
  background: #63b6e5;
}
</style>
<div id='map-two' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapTwo = L.mapbox.map('map-two', 'mapbox.light')
.setView([37.8, -96], 4);

var myLayer = L.mapbox.featureLayer().addTo(mapTwo);

var geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      icon: {
        className: 'my-icon icon-dc', // class name to style
        html: '&#9733;', // add content inside the marker
        iconSize: null // size of icon, use null to set the size in CSS
      }
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    },
    properties: {
      icon: {
        className: 'my-icon icon-sf', // class name to style
        html: '&#9733;', // add content inside the marker
        iconSize: null // size of icon, use null to set the size in CSS
      }
    }
  }
];
myLayer.on('layeradd', function(e) {
  var marker = e.layer,
    feature = marker.feature;
  marker.setIcon(L.divIcon(feature.properties.icon));
});
myLayer.setGeoJSON(geojson);

mapTwo.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

Adding tooltips

You can add tooltips with simplestyle in your GeoJSON or with JavaScript.

With simplestyle

In your GeoJSON, add title and description keys to each feature’s properties and Mapbox.js will add the tooltips automatically. In the example below, we added these fields to the GeoJSON. Click the markers to trigger the tooltip and then click view source to see the code.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map-tooltips' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapTooltips = L.mapbox.map('map-tooltips', 'mapbox.light')
  .setView([37.8, -96], 4);
var myLayer = L.mapbox.featureLayer().addTo(mapTooltips);

var geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      title: 'Mapbox DC',
      description: '1714 14th St NW, Washington DC',
      'marker-color': '#3ca0d3',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    },
    properties: {
      title: 'Mapbox SF',
      description: '155 9th St, San Francisco',
      'marker-color': '#63b6e5',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  }
];
myLayer.setGeoJSON(geojson);
mapTooltips.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

The title and description values accept simple HTML. You can add links, images, headline tags, and lists.

With JavaScript

You can customize the content of each popup with bindPopup. In this example, we added an image key to each feature. We included a reference to the field in bindPopup() to make the image appear inside the tooltip.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map-tooltips-js' class='map'> </div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapTooltipsJS = L.mapbox.map('map-tooltips-js', 'mapbox.light')
  .setView([37.8, -96], 4);
var myLayer = L.mapbox.featureLayer().addTo(mapTooltipsJS);

var geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      title: 'Mapbox DC',
      description: '1714 14th St NW, Washington DC',
      image: 'https://farm9.staticflickr.com/8604/15769066303_3e4dcce464_n.jpg',
      icon: {
        iconUrl: 'https://www.mapbox.com/mapbox.js/assets/images/astronaut1.png',
        iconSize: [50, 50], // size of the icon
        iconAnchor: [25, 25], // point of the icon which will correspond to marker's location
        popupAnchor: [0, -25], // point from which the popup should open relative to the iconAnchor
        className: 'dot'
      }
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    },
    properties: {
      title: 'Mapbox SF',
      description: '155 9th St, San Francisco',
      image: 'https://farm9.staticflickr.com/8571/15844010757_63b093d527_n.jpg',
      icon: {
        iconUrl: 'https://www.mapbox.com/mapbox.js/assets/images/astronaut2.png',
        iconSize: [50, 50], // size of the icon
        iconAnchor: [25, 25], // point of the icon which will correspond to marker's location
        popupAnchor: [0, -25], // point from which the popup should open relative to the iconAnchor
        className: 'dot'
      }
    }
  }
];

// Set a custom icon on each marker based on feature properties.
myLayer.on('layeradd', function(e) {
  var marker = e.layer,
    feature = marker.feature;
  marker.setIcon(L.icon(feature.properties.icon));
  var content = '<h2>' + feature.properties.title + '</h2><img src="' + feature.properties.image + '" alt="">';
  marker.bindPopup(content);
});
myLayer.setGeoJSON(geojson);
mapTooltipsJS.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

More examples

You can completely customize your tooltips with Mapbox.js. Here are more examples to show you how:

Clustering markers

For dense data, try markerclusters to make your map easy to navigate. In the example below, we load a GeoJSON file, create a clustergroup from the data, and then add it to the map. Since markercluster is a plugin, you’ll need to add additional CSS and JS to enable it.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/leaflet.markercluster.js'></script>
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.css' rel='stylesheet' />
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.Default.css' rel='stylesheet' />
<div id='map-cluster' class='map'></div>
<script>
L.mapbox.accessToken = '<your access token here>';
var mapCluster = L.mapbox.map('map-cluster')
  .setView([38.9, -77], 11)
  .addLayer(L.mapbox.tileLayer('mapbox.light'));
L.mapbox.featureLayer()
  .loadURL('/help/data/examples/stations.geojson')
  .on('ready', function(e) {
    var clusterGroup = new L.MarkerClusterGroup();
    e.target.eachLayer(function(layer) {
      clusterGroup.addLayer(layer);
    });
    mapCluster.addLayer(clusterGroup);
  });
mapCluster.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

More examples

Here are more markercluster examples, including some that customize the clusters:

Toggling layers

You can help users sift through your marker points by adding a filter. In this example, the script automatically creates a toggle option for each marker symbol. The code scales with the data and will only add a toggle if the symbol is in the data file.

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title></title>
  <script src='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.js'></script>
  <link href='https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    .map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<style>
.filter-ui {
  background: #fff;
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 100;
  padding: 10px;
  border-radius: 3px;
}

.filter-ui input {
  vertical-align: middle;
}
</style>
<nav id='filters' class='filter-ui'></nav>
<div id='map-toggle' class='map'></div>
<script>
L.mapbox.accessToken = '<your access token here>';

var mapToggle = L.mapbox.map('map-toggle')
  .setView([38.9, -77], 11)
  .addLayer(L.mapbox.tileLayer('mapbox.light'));

var filters = document.getElementById('filters');

var markers = L.mapbox.featureLayer().loadURL('/help/data/examples/dc-weekend-picks.geojson');

markers.on('ready', function(e) {
  var typesObj = {},
    types = [];
  var features = e.target._geojson.features;
  for (var i = 0; i < features.length; i++) {
    typesObj[features[i].properties['marker-symbol']] = true;
  }
  for (var key in typesObj) {
    if ({}.hasOwnProperty.call(typesObj, key)) {
      types.push(key);
    }
  }
  var checkboxes = [];
  for (var j = 0; j < types.length; j++) {
    var item = filters.appendChild(document.createElement('div'));
    var checkbox = item.appendChild(document.createElement('input'));
    var label = item.appendChild(document.createElement('label'));
    checkbox.type = 'checkbox';
    checkbox.id = types[j];
    checkbox.checked = true;
    label.innerHTML = types[j];
    label.setAttribute('for', types[j]);
    checkbox.addEventListener('change', update);
    checkboxes.push(checkbox);
  }

  function update() {
    var enabled = {};
    for (var k = 0; k < checkboxes.length; k++) {
      if (checkboxes[k].checked) enabled[checkboxes[k].id] = true;
    }
    markers.setFilter(function(feature) {
      return feature.properties['marker-symbol'] in enabled;
    });
  }
}).addTo(mapToggle);
mapToggle.scrollWheelZoom.disable();
</script>
</body>
</html>
View source

To use data from a Mapbox project map ID, check out the original example.

More examples

We have more examples to help you filter or toggle your markers or complete layers:

Next steps

Congratulations! You’re now a friend to markers big and small! We hope that this guide has given you the right tools, code, and inspiration to add the markers that you want to your map.

Here are some more tools to help you generate, validate, or format GeoJSON:

  • geojson.io - create GeoJSON on the fly, allows you to add additional data to each feature.
  • GeoJSON Hint - validate GeoJSON. If there’s an error in your GeoJSON, this tool will find it.
  • toGeoJSON - convert at KML or GPX to GeoJSON.
  • csv2geojson - convert a CSV file to GeoJSON.
Additional questions? Ask our support team or learn more about How Mapbox Works.