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

# Make a choropleth map, part 2: add interactivity

In [part 1](https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/), you styled US population density data in the Mapbox Studio style editor and published a new style. In part 2, you will make this style come to life with interactions using Mapbox GL JS.

## How Mapbox Studio and Mapbox GL JS work together

In the last guide, you used the Mapbox Studio style editor to design your map and create a style. But what did the software produce when you clicked Publish?

### What is a style?

The style is the most important part of making a web map: it contains all the rules for what features to draw on the webpage and how to draw them. Both Mapbox Studio and Mapbox GL JS interact directly with your style: the Mapbox Studio style editor is a visual interface for creating the style, and Mapbox GL JS is used to add the style to a webpage and interact with it directly by adding and changing the layers and sources in response to browser events.

A [map style](https://docs.mapbox.com/help/glossary/style/) is a JSON object in the [Mapbox Style Specification](https://docs.mapbox.com/style-spec/) that contains all the things the browser needs to draw your map correctly. Its main parts are:

-   **`sources`**: links to all the data that will be styled on the map. When creating a style with the Mapbox Studio style editor, sources are raster and vector tilesets in your Mapbox account.
-   **`sprite`**: a link to all the images and icons that are used in the style.
-   **`glyphs`**: a link to all the fonts that are used in the style.
-   **`layers`**: a list of rules for how the data in `sources` should be displayed on the map.

When you added the population density data to your Mapbox Studio style in part 1, a link to it was also added to the list of sources in a style object (we normally refer to these as "styles"). Similarly, when you added the population density layer and gave it styling rules for the each category of data, that layer was also added to the list of layers in your style.

## Prerequisites

Here's what you need to get started:

-   **Familiarity with front-end development**: Beginner experience with HTML, CSS and JavaScript.
-   **A Code editor**: A program like [Visual Studio Code](https://code.visualstudio.com/).
-   **A Mapbox access token**: Find yours on the [Access token page](https://console.mapbox.com/account/access-tokens/) of your Developer Console.
-   The [**style URL**](https://docs.mapbox.com/help/glossary/style-url/) for your style. From your [Styles](https://www.mapbox.com/studio) page, click on the **Menu ** button next to your population density style and then click the  clipboard icon to copy the **Style URL**.
-   [**Mapbox GL JS**](https://docs.mapbox.com/mapbox-gl-js/): is a JavaScript library for building web maps and applications with Mapbox.

> **Note: Tutorial series: Make a choropleth map**
> 
> This series of tutorials teaches you how to a create a map to visualize data across a region.
> 
> -   [Part 1: Create a style](https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/)
> -   Part 2: Add Interactivity

> **Note: Accessing the Full Sample Code**
> 
> If you wish to copy the full code snippet in its entirety instead of following along with the tutorial, view the full code in **Step 11 - The Finished Product**.

## Create a webpage

First, create a webpage to host the map.

1.  Open your IDE and create a file called `index.html`.
2.  Set up the file by adding Mapbox GL JS and its associated CSS file in the header by copying and pasting the code below:

```html
<!DOCTYPE html>
<html>
  <head>
    <style>
    </style>
    <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"
    />
  </head>
<body>
  <script>
    
  </script>
</body>
</html>
```

3.  Next, create a map container, an information box, and a legend by adding the code below to the body of your file, above the script tags:

```html
<div id="map"></div>
<div class="map-overlay" id="features">
  <h2>US population density</h2>
  <div id="pd"><p>Hover over a state!</p></div>
</div>
<div class="map-overlay" id="legend"></div>
```

4.  Now, apply CSS to style the layout, paste the code below into the style section of the header:
    -   This is particularly important for the `map` div, which won't show up on the page until you give it a `height`.

If you open the `HTML` file in your browser now, the page will appear mostly blank, as seen in the screenshot at the bottom of the page. In the next step, you will add the map to your page and the project will start taking shape.

```css
body {
  margin: 0;
  padding: 0;
}

h2,
h3 {
  margin: 10px;
  font-size: 18px;
}

h3 {
  font-size: 16px;
}

p {
  margin: 10px;
}

/**
* Create a position for the map
* on the page */
#map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}

/**
* Set rules for how the map overlays
* (information box and legend) will be displayed
* on the page. */
.map-overlay {
  position: absolute;
  bottom: 0;
  right: 0;
  background: #fff;
  margin-right: 20px;
  font-family: Arial, sans-serif;
  overflow: auto;
  border-radius: 3px;
}

#features {
  top: 0;
  height: 100px;
  margin-top: 20px;
  width: 250px;
}

#legend {
  padding: 10px;
  box-shadow: 0 1px 2px rgba(0 0 0 0.1);
  line-height: 18px;
  height: 150px;
  margin-bottom: 40px;
  width: 100px;
}

.legend-key {
  display: inline-block;
  border-radius: 20%;
  width: 10px;
  height: 10px;
  margin-right: 5px;
}
```

![Publishing the style](https://docs.mapbox.com/help/assets/ideal-img/tutorials--choropleth-studio-gl-pt-2--blank-map-page.80d9de1.480.png)

## Initialize map

Now that you've added structure to the page, you can start writing some JavaScript to add the map to your webpage.

**All the code from this step should be between `script` tags.**

1.  First, you'll need to add an access token to your code.
    -   Without an access token, you will not be able to access Mapbox services.
    -   To grab an access token, go to your [Developer Console](https://console.mapbox.com/) and copy the access token from the top right corner of the webpage.

2.  Now that you've added the structure of the page, you can add a map object into the `map` div using the code below.

```js
const map = new mapboxgl.Map({
  accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
  container: 'map', // container id
  style: 'your-style-url' // replace this with your style URL
});
```

3.  Replace `'your-style-url'` in the code with the URL from the style you created in [Part 1: Create a style](https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/):
    -   To grab the style URL, go to your [Styles](https://console.mapbox.com/studio/) page and click the  button next to the name of the style.
    -   In the window that appears, scroll down to **Developer Resources**, make sure **Web** is selected and copy the **Style URL**.

Your browser doesn't support HTML5 video. Open [link to the video](https://docs.mapbox.com/help/help/assets/medias/tutorials--choropleth-studio-gl-pt-2--grab-style-url-392ebfa328757ceca438dffec85ca066.mp4).

4.  Save your HTML file and open it in a browser. The page should appear like so:

> **Note (warning): Troubleshooting**
> 
> If your map is not showing the style, make sure your style is published by going back to your [Styles](https://console.mapbox.com/studio/) page, opening the style you created and hitting the publish button in the top right corner of the style editor.
> 
> You may need to wait for a few minutes for changes to appear.

## Add the on load map event

Now you will add data to the legend and functionality to the information window to show the population density for whatever state the cursor is hovering over a state.

These two features rely on the style being loaded onto the map, so it's important to make sure the style is loaded before any of this code is executed.

Initializing the map not only creates a container in the `map` div, but also tells the browser to request the Mapbox Studio style you created in part 1. This can take variable amounts of time depending on how quickly the Mapbox server can respond to that request, but fortunately, the map object can tell your browser about certain events that occur when the map's state changes, for example when the map has loaded.

Through the `map.on` method, you can make sure that none of the rest of your code is executed until that event occurs by placing it in a [callback function](https://github.com/maxogden/art-of-node#callbacks) that is called when the `load` event occurs.

Create the on load event by adding the code below to your code:

```js
map.on('load', () => {
  // the rest of the code will go in here
});
```

## Create arrays of intervals and colors

Create a list of the stops that reflect the stops you added to your style, so you can add data to the legend to your map in a later step.

Paste this code inside of the `load` callback function:

```js
const layers = [
  '0-10',
  '10-20',
  '20-50',
  '50-100',
  '100-200',
  '200-500',
  '500-1000',
  '1000+'
];
const colors = [
  '#FFEDA0',
  '#FED976',
  '#FEB24C',
  '#FD8D3C',
  '#FC4E2A',
  '#E31A1C',
  '#BD0026',
  '#800026'
];
```

## Add data to the legend

The following code adds information to the legend on the map, by iterating through the list of layers you defined above and adds a legend element for each one based on the name of the layer and its color.

Paste this code inside of the `load` callback function below the data from the last step:

```js
// create legend
const legend = document.getElementById('legend');

layers.forEach((layer, i) => {
  const color = colors[i];
  const item = document.createElement('div');
  const key = document.createElement('span');
  key.className = 'legend-key';
  key.style.backgroundColor = color;

  const value = document.createElement('span');
  value.innerHTML = `${layer}`;
  item.appendChild(key);
  item.appendChild(value);
  legend.appendChild(item);
});
```

## Add the information window

When the cursor is hovering over a state, the information window should show the population density information for that state. If the cursor is not hovering over a state, the information window should say, "Hover over a state!"

To do this, add a listener for the `mousemove` event, identify which state is at the location of the cursor if any, and update the information window:

```js
map.on('mousemove', (event) => {
  const states = map.queryRenderedFeatures(event.point, {
    layers: ['statedata']
  });
  document.getElementById('pd').innerHTML = states.length
    ? `<h3>${states[0].properties.name}</h3><p><strong><em>${states[0].properties.density}</strong> people per square mile</em></p>`
    : `<p>Hover over a state!</p>`;
});
```

> **Note (warning): Troubleshooting**
> 
> If nothing happens when you hover over a state, go back into your style in the [**Style Editor**](https://www.mapbox.com/studio) and make sure you've renamed the layer to `statedata`. If this layer name does not match the code above, you will experience errors.
> 
> You may need to wait several minutes for changes to appear.

## Final touches

Almost done! A couple last little steps:

### Cursor

Add a single line of code to give the map the default pointer cursor.

```js
map.getCanvas().style.cursor = 'default';
```

### Map bounds

Make sure the map shows the continental U.S. when it's loaded by setting the bounds of the map on load:

```js
map.fitBounds([
  [-133.2421875, 16.972741],
  [-47.63671875, 52.696361]
]);
```

## Finished Product

### Finished code snippet

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Demo: Make a choropleth map</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <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;
      }

      h2,
      h3 {
        margin: 10px;
        font-size: 18px;
      }

      h3 {
        font-size: 16px;
      }

      p {
        margin: 10px;
      }

      .map-overlay {
        position: absolute;
        bottom: 0;
        right: 0;
        background: #fff;
        margin-right: 20px;
        font-family: Arial, sans-serif;
        overflow: auto;
        border-radius: 3px;
      }

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

      #features {
        top: 0;
        height: 100px;
        margin-top: 20px;
        width: 250px;
      }

      #legend {
        padding: 10px;
        box-shadow: 0 1px 2px rgb(0 0 0 / 10%);
        line-height: 18px;
        height: 150px;
        margin-bottom: 40px;
        width: 100px;
      }

      .legend-key {
        display: inline-block;
        border-radius: 20%;
        width: 10px;
        height: 10px;
        margin-right: 5px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <div class="map-overlay" id="features">
      <h2>US population density</h2>
      <div id="pd"><p>Hover over a state!</p></div>
    </div>
    <div class="map-overlay" id="legend"></div>

    <script>
      // define access token
      // create map
      const map = new mapboxgl.Map({
        accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
        container: 'map', // container id
        style: 'mapbox://styles/examples/cjgioozof002u2sr5k7t14dim' // map style URL from Mapbox Studio
      });

      // wait for map to load before adjusting it
      map.on('load', () => {
        // make a pointer cursor
        map.getCanvas().style.cursor = 'default';

        // set map bounds to the continental US
        map.fitBounds([
          [-133.2421875, 16.972741],
          [-47.63671875, 52.696361]
        ]);

        // define layer names
        const layers = [
          '0-10',
          '10-20',
          '20-50',
          '50-100',
          '100-200',
          '200-500',
          '500-1000',
          '1000+'
        ];
        const colors = [
          '#FFEDA0',
          '#FED976',
          '#FEB24C',
          '#FD8D3C',
          '#FC4E2A',
          '#E31A1C',
          '#BD0026',
          '#800026'
        ];

        // create legend
        const legend = document.getElementById('legend');

        layers.forEach((layer, i) => {
          const color = colors[i];
          const item = document.createElement('div');
          const key = document.createElement('span');
          key.className = 'legend-key';
          key.style.backgroundColor = color;

          const value = document.createElement('span');
          value.innerHTML = `${layer}`;
          item.appendChild(key);
          item.appendChild(value);
          legend.appendChild(item);
        });

        // change info window on hover
        map.on('mousemove', (event) => {
          const states = map.queryRenderedFeatures(event.point, {
            layers: ['statedata']
          });
          document.getElementById('pd').innerHTML = states.length
            ? `<h3>${states[0].properties.name}</h3><p><strong><em>${states[0].properties.density}</strong> people per square mile</em></p>`
            : `<p>Hover over a state!</p>`;
        });
      });
    </script>
  </body>
</html>
```

Nice job! For more things you can do with Mapbox Studio, explore the [Mapbox Studio Manual](https://docs.mapbox.com/studio-manual/). For more information on Mapbox GL JS and how it works, read the [How web apps work](https://docs.mapbox.com/help/dive-deeper/web-apps/) guide.

## Next steps

**Congratulations!** You have created an interactive choropleth map!

### What we covered

-   Understanding how Mapbox Studio & Mapbox GL JS work together
-   Creating an HTML file to instantiate a Mapbox map
-   Adding custom UI to the Map
-   Using `queryRenderedFeatures` to retrieve map data
-   Centering a map using `fitBounds`

### Learn more

If you are interested in data visualization see our tutorial [Create a map with a data visualization component](https://docs.mapbox.com/help/tutorials/create-a-map-with-data-visualization-component/)