All docschevron-rightHelpchevron-rightarrow-leftTutorialschevron-rightWork with markers in Mapbox.js

Work with markers in Mapbox.js

Intermediate
JavaScript
alert
LEGACY

Mapbox.js is no longer in active development. To learn more about our newer mapping tools see Add custom markers in Mapbox GL 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 in Mapbox.js.

Getting started

For this guide you'll need your API access token. You can find your access token on your Account page. To better understand each example, you can copy the full source code into your own local project and experiment. We adapted many of these demos from Mapbox.js examples.

Add markers

You can add markers to your map using Leaflet or with GeoJSON using Mapbox.js.

Add markers in Leaflet

You can add a DOM marker to your map with L.marker. In the example below, we added a marker to the map by knowing its coordinates. Use this technique when you have only a few markers to add.

<div id='map-leaflet' class='map'></div>
<script>
const mapLeaflet = L.mapbox.map('map-leaflet')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));

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

mapLeaflet.scrollWheelZoom.disable();
</script>

Add markers with GeoJSON in Mapbox.js

You can also save your marker coordinates as GeoJSON and then load your GeoJSON on a map with Mapbox.js. In this example, we added the coordinates of the Mapbox D.C. and San Francisco offices to our inline GeoJSON. The GeoJSON format organizes features, especially when working with larger data files.

<div id='map_geo' class='map'></div>
<script>
const geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    }
  }
];

const mapGeo = L.mapbox.map('map_geo')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));

const myLayer = L.mapbox.featureLayer().setGeoJSON(geojson).addTo(mapGeo);
mapGeo.scrollWheelZoom.disable();
</script>

You can also load GeoJSON as an external file hosted locally or on GitHub. In the next section, you'll learn how to style GeoJSON markers with the simplestyle specification.

If you're new to working with GeoJSON, here are some tools to help you generate, validate, or format GeoJSON:

Style markers

To style a marker, you can add simplestyle to your GeoJSON, load a custom image, or create your own markers with HTML and CSS.

Style markers with simplestyle

The simplestyle spec is a styling convention for GeoJSON. This means that you can add specific keys and values to each marker to change a marker's color, symbol, and size.

Here are all the styling options available as keys and values:

KeyValueExample
"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.

<div id='map_simple' class='map'></div>
<script>
const geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      'marker-color': '#3bb2d0',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  },
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-122.413682, 37.775408]
    },
    properties: {
      'marker-color': '#3bb2d0',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  }
];

const mapSimple = L.mapbox.map('map_simple')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));
const myLayer = L.mapbox.featureLayer().setGeoJSON(geojson).addTo(mapSimple);
mapSimple.scrollWheelZoom.disable();
</script>

Style markers with an image

You can define a custom marker image in your GeoJSON by adding an icon object to each feature's properties. In this example, L.icon is used to set the marker image to each feature's iconURL.

<div id='map-one' class='map'></div>
<script>
const mapOne = L.mapbox.map('map-one')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));
const myLayer = L.mapbox.featureLayer().addTo(mapOne);

const geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      icon: {
        iconUrl: 'https://docs.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://docs.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', (event) => {
  event.layer.setIcon(L.icon(event.layer.feature.properties.icon));
});
myLayer.setGeoJSON(geojson);
mapOne.scrollWheelZoom.disable();
</script>

Style markers with HTML and CSS

If you'd like to customize your markers even more, you can replace the standard marker with a <div>, assign it a class, and then style it with CSS using L.divIcon. In this example, you'll follow a similar pattern as you did when adding a marker image, but instead you'll assign a class name to the features and then add CSS to style it.

<style>
.my-icon {
  border-radius: 100%;
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  color: white;
}

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

.icon-sf {
  background: #3bb2d0;
}
</style>
<div id='map-two' class='map'></div>
<script>
const mapTwo = L.mapbox.map('map-two')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));

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

const geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      icon: {
        className: 'my-icon icon-dc', // class name to style
        html: '★', // add content inside the marker, in this case a star
        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: '★', // add content inside the marker, in this case a star
        iconSize: null // size of icon, use null to set the size in CSS
      }
    }
  }
];
myLayer.on('layeradd', (event) => {
  event.layer.setIcon(L.divIcon(event.layer.feature.properties.icon));
});
myLayer.setGeoJSON(geojson);

mapTwo.scrollWheelZoom.disable();
</script>

Add popups

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

Add popups with simplestyle

Simplestyle allows you to add popups automatically if you add title and description keys to each feature's properties. In the example below, these fields are added to the GeoJSON. Click the markers to trigger the popup.

<div id='map-popups' class='map'></div>
<script>
const mapPopups = L.mapbox.map('map-popups')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));
const myLayer = L.mapbox.featureLayer().addTo(mapPopups);

const geojson = [
  {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77.031952, 38.913184]
    },
    properties: {
      title: 'Mapbox DC',
      description: '1714 14th St NW, Washington DC',
      'marker-color': '#3bb2d0',
      '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': '#3bb2d0',
      'marker-size': 'large',
      'marker-symbol': 'rocket'
    }
  }
];
myLayer.setGeoJSON(geojson);
mapPopups.scrollWheelZoom.disable();
</script>

You can add HTML to you popups by adding it to the title and description values in your GeoJSON. This allows you to add links, images, videos, lists, and other HTML elements to your popups.

Add popups with JavaScript

You can customize the content of each popup with the L.bindPopup method. In this example, an image key is added to each feature's property object, and a reference to this key when is included when bindPopup() is called to make the image appear inside the popup.

<div id='map-popups-js' class='map'></div>
<script>
const mapPopupsJS = L.mapbox.map('map-popups-js')
  .setView([37.8, -96], 4)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));
const myLayer = L.mapbox.featureLayer().addTo(mapPopupsJS);

const 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://docs.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://docs.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', (event) => {
  event.layer.setIcon(L.icon(event.layer.feature.properties.icon));
  const content = `<p><strong>${layer.feature.properties.title}</strong></p><img src='${layer.feature.properties.image}' alt=''>`;
  layer.bindPopup(content);
});
myLayer.setGeoJSON(geojson);
mapPopupsJS.scrollWheelZoom.disable();
</script>

More examples

You can further customize your popups with Mapbox.js. Here are more examples to get you started:

Cluster markers

For dense point data, try the Leaflet plug-in Markercluster to visualize your data. In the example below, we load an external GeoJSON file, create a clustergroup from the data, and add it to the map. Since Markercluster is a plugin, you'll need to add additional CSS and JS to enable it.

<script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v3.2.1/leaflet.markercluster.js'></script>
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v3.2.1/MarkerCluster.css' rel='stylesheet' />
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v3.2.1/MarkerCluster.Default.css' rel='stylesheet' />
<div id='map-cluster' class='map'></div>
<script>
const mapCluster = L.mapbox.map('map-cluster')
  .setView([38.9, -77], 11)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));
L.mapbox.featureLayer()
  .loadURL('/help/data/stations.geojson')
  .on('ready', (event) => {
    const clusterGroup = new L.MarkerClusterGroup();
    event.target.eachLayer((layer) => clusterGroup.addLayer(layer));
    mapCluster.addLayer(clusterGroup);
  });
mapCluster.scrollWheelZoom.disable();
</script>

More examples

For more ideas of what you can do with clusters in Mapbox.js, explore these examples:

Toggle layers

Finally, take a look at how to toggle layers in Mapbox.js. You can help users sift through your markers by adding filters to let them turn layers on and off. In this example, the script automatically creates a toggle option for each transit line and will only add a new layer to the toggle list if its line is declared in the GeoJSON.

<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>

const mapToggle = L.mapbox.map('map-toggle')
  .setView([38.9, -77], 11)
  .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/light-v11'));

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

const markers = L.mapbox.featureLayer().loadURL('/help/data/examples/stations.geojson');

markers.on('ready', (event) => {
  const typesObj = {},
    types = [];
  const features = event.target._geojson.features;
  for (const feature of features) {
    typesObj[feature.properties.line] = true;
  }
  for (const key in typesObj) {
    if ({}.hasOwnProperty.call(typesObj, key)) {
      types.push(key);
    }
  }
  const checkboxes = [];
  for (const type of types) {
    const item = filters.appendChild(document.createElement('div'));
    const checkbox = item.appendChild(document.createElement('input'));
    const label = item.appendChild(document.createElement('label'));
    checkbox.type = 'checkbox';
    checkbox.id = type;
    checkbox.checked = true;
    label.innerHTML = `${type}`;
    label.setAttribute('for', type);
    checkbox.addEventListener('change', update);
    checkboxes.push(checkbox);
  }

  function update() {
    const enabled = {};
    for (const checkbox of checkboxes) {
      if (checkbox.checked) enabled[checkbox.id] = true;
    }
    markers.setFilter((feature) => feature.properties.line in enabled);
  }
}).addTo(mapToggle);
mapToggle.scrollWheelZoom.disable();
</script>

More examples

For more ideas on how to filter or toggle your markers, explore these examples:

Next steps

You now have the tools, code, and inspiration to add any markers you need to your map. For more ways to extend your Mapbox.js project, explore the Build a store locator tutorial.