> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/help/ja/llms.txt)

# Add custom markers in Mapbox GL JS

Mapbox GL JS includes a default blue pin [`Marker`](https://docs.mapbox.com/help/ja/glossary/marker/), but because each marker is an HTML element, you can fully customize its appearance using CSS. This means you can use any image, icon, or styled element as a marker on your map.

In this tutorial, you will build an interactive web map with custom image markers and clickable popups that display information about each location.

Your final map will look like this:

## Prerequisites

To follow along with this guide you'll need:

-   **Familiarity with front-end development**: Beginner experience with HTML, CSS and JavaScript.
-   **Mapbox account**: [Sign up](https://account.mapbox.com/auth/signup/) for free or [log in](https://console.mapbox.com/) if you already have an account.
-   **A Code editor**: A program like [Visual Studio Code](https://code.visualstudio.com/).

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

> **Related content (video): [How to add markers to a map with Mapbox GL JS](null)**
> 
> Follow along with this tutorial to learn how to initialize a web map, add GeoJSON, and add an HTML marker for each point.

> **Note: Accessing Sample Code**
> 
> If you wish to copy the code sample in its entirety instead of following along with the tutorial, view the [full code snippet here](https://docs.mapbox.com/help/ja/tutorials/custom-markers-gl-js/?step=8).

## Create an HTML file and initialize your map

Start by creating a basic HTML page with a full-screen Mapbox GL JS map.

1.  Create a file named `index.html` and open it in your code editor.
2.  Copy and paste the code below into your file.
3.  Replace `YOUR_MAPBOX_ACCESS_TOKEN` with your public access token. If you are logged into your Mapbox account, your token is automatically added to the code snippet.
4.  Open `index.html` in a browser. You should see a light-themed map of the United States.

```html
<!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.mapbox.com/mapbox-gl-js/v3.25.0/mapbox-gl.js"></script>
    <link
      href="https://api.mapbox.com/mapbox-gl-js/v3.25.0/mapbox-gl.css"
      rel="stylesheet"
    />
    <style>
      body {
        margin: 0;
        padding: 0;
      }

      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>

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

    </script>
  </body>
</html>
```

> **Note: Mapbox GL JS Map options**
> 
> The [`Map`](https://docs.mapbox.com/mapbox-gl-js/api/map/) constructor accepts several options:
> 
> -   `container`: the `id` of the `<div>` element where the map renders. Here it's `'map'`.
> -   `style`: a [style URL](https://docs.mapbox.com/api/maps/styles/). This tutorial uses the Mapbox Light style.
> -   `center`: the starting position as `[longitude, latitude]`.
> -   `zoom`: the initial zoom level.

## Define marker locations with GeoJSON

Next, define where your markers will appear by creating a [GeoJSON](https://docs.mapbox.com/help/ja/glossary/geojson/) object. GeoJSON is a standard format for encoding geographic data. Each feature has a `geometry` (the location) and `properties` (data you want to associate with that location, such as a name or description).

> **Note: GeoJSON is not required**
> 
> GeoJSON is not required for creating markers — a marker only needs a longitude/latitude pair. GeoJSON is used in this tutorial because it's a commonly used standard format that works well in JavaScript code and is compatible with other Mapbox products. You could also loop over a plain array of coordinates or objects from any data source.

Copy and paste the highlighted `geojson` variable below the `Map` initialization, inside the `<script>` tag:

```js
    const map = new mapboxgl.Map({
        accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
        // ... other Map options
      });

    // highlight-start
    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'
          }
        }
      ]
    };
    // highlight-end
```

Each feature's `geometry.coordinates` determines where a marker will be placed. The `properties` (`title` and `description`) will be displayed in popups later.

> **Note: 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](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) to load from a local file or third-party API.

## Add markers to the map

Now loop through the GeoJSON features to create a marker for each location. By default, `new mapboxgl.Marker()` renders the built-in blue pin SVG:

Add the following code after the `geojson` variable, before the closing `</script>` tag:

```js
    // add markers to map
    for (const feature of geojson.features) {
      // make a marker for each feature and add to the map
      new mapboxgl.Marker().setLngLat(feature.geometry.coordinates).addTo(map);
    }
```

Save and refresh your browser. You should see two blue pin markers:

![Map of the United States showing two default blue pin markers, one on the east coast near Washington, D.C. and one on the west coast near San Francisco.](https://docs.mapbox.com/help/ja/assets/ideal-img/custom-markers-gl-js-default-markers.e4e90eb.480.png)

## Customize the markers with HTML and CSS

The `Marker` constructor accepts an optional HTML element as its first argument. When you pass in a custom element, it replaces the default blue pin entirely. This is the key to custom markers: you create an HTML element, style it with CSS, and the marker displays your element on the map instead of the default SVG.

### Update the JavaScript

Replace the `for` loop from the previous step with the highlighted code below. Instead of using the default marker, this creates a `<div>` element with a CSS class of `marker` and passes it to the `Marker` constructor:

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

      // pass the element to the Marker constructor to replace the default
      new mapboxgl.Marker(el).setLngLat(feature.geometry.coordinates).addTo(map);
      // highlight-end
    }
```

If you save and refresh now, the markers won't be visible yet because the `<div>` elements have no size or appearance. You need CSS to make them visible.

### Add CSS for the markers

Add the following CSS inside your `<style>` tag, below the `#map` rule. This uses `background-image` to display a custom image, sets the marker size to 50×50 pixels, and changes the cursor on hover:

```css
    .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;
    }
```

Save and refresh. Your markers should now display the custom Mapbox icon image instead of the default blue pin.

> **Note: Other ways to customize markers**
> 
> Using `background-image` in CSS is one approach. Since the marker is a standard HTML element, you could also use an `<img>` tag, inline SVG, an icon font like [Font Awesome](https://fontawesome.com), or emoji. Any HTML you can style with CSS works as a marker.

## Add popups to the markers

Next, add a [`Popup`](https://docs.mapbox.com/mapbox-gl-js/api/markers/#popup) to each marker so that clicking it displays the location's information from the GeoJSON `properties`.

Update the `Marker` creation in the `for` loop to chain a [`setPopup`](https://docs.mapbox.com/mapbox-gl-js/api/markers/#marker#setpopup) call. This creates a popup and attaches it to the marker, so clicking the marker toggles the popup open and closed:

```js
    // add markers to map
    for (const feature of geojson.features) {
      const el = document.createElement('div');
      el.className = 'marker';

      // highlight-start
      new mapboxgl.Marker(el)
        .setLngLat(feature.geometry.coordinates)
        .setPopup(
          new mapboxgl.Popup({ offset: 25 })
            .setHTML(
              `<h3>${feature.properties.title}</h3><p>${feature.properties.description}</p>`
            )
        )
        .addTo(map);
      // highlight-end
    }
```

Here's what's happening:

-   **`setPopup()`** attaches a `Popup` instance to the marker. Mapbox GL JS automatically handles showing and hiding the popup when the marker is clicked.
-   **`new mapboxgl.Popup({ offset: 25 })`** creates the popup with a 25-pixel vertical offset, so the popup shows above the marker rather than overlapping it.
-   **`setHTML()`** sets the popup content using the `title` and `description` from each GeoJSON feature's `properties`. You can display any data stored in your GeoJSON here.

## Style the popups with CSS

As a final touch, add CSS to style the popups. Add the following rules inside your `<style>` tag, below the `.marker` rule:

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

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

Save your file and refresh your browser. Click a marker to see the styled popup with the location information.

## Finished product

You've built an interactive map with custom image markers and informational popups using Mapbox GL JS.

### Finished interactive map

### Finished code snippet

```html
<!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.mapbox.com/mapbox-gl-js/v3.25.0/mapbox-gl.js"></script>
    <link
      href="https://api.mapbox.com/mapbox-gl-js/v3.25.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>
      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({
        accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
        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:

-   [Add data to a style](https://docs.mapbox.com/help/ja/tutorials/add-data-to-mapbox-style/) using Mapbox Studio and Mapbox GL JS.
-   [Build a store locator](https://docs.mapbox.com/help/ja/tutorials/building-a-store-locator/) using Mapbox GL JS.
-   [Show changes over time](https://docs.mapbox.com/help/ja/tutorials/show-changes-over-time/) with Mapbox GL JS.
-   [Analyze data with Turf.js](https://docs.mapbox.com/help/ja/tutorials/analysis-with-turf/) and Mapbox GL JS.

Explore our [Mapbox GL JS examples](https://docs.mapbox.com/mapbox-gl-js/examples/) for more ideas on how to extend your project and code to get you started.