Skip to main content

Use Mapbox GL JS in a Svelte app

Prerequisite
Familiarity with Svelte and front-end development concepts.

Svelte is a popular JavaScript web framework used for increasing client performance. Since Svelte manipulates the DOM, it can be confusing to connect Svelte with other libraries that also manipulate the DOM and manage state — like Mapbox GL JS.

In this tutorial, you will learn how to create a Svelte web app that uses Mapbox GL JS to render a map, display the coordinates of the map center point and its zoom level, then update the display when a user interacts with the map. You will be able to use the principles discussed in this tutorial to create more complex apps that use both Svelte and Mapbox GL JS. This tutorial shows code for Svelte Bindings and Component Lifecycles.

Getting started

  • A Mapbox access token. Your Mapbox access tokens are on your Account page.
  • Mapbox GL JS. Mapbox GL JS is a JavaScript library used for building web maps.
  • A text editor. Use the text editor of your choice for writing HTML, CSS, and JavaScript.
  • Git. You will need to be able to run git commands from your command line.
  • Node.js and npm. To run the commands necessary to run your Svelte app locally, install Node.js and npm.
  • Working familiarity with Svelte. You don't need to have a lot of experience using Svelte to complete this tutorial, but you should be familiar with the underlying concepts and workflows.

Set up the Svelte app structure

To get started, clone Svelte's "template" GitHub repository. This will create a base layer to build any Svelte app upon. Wherever you want the folder for this project to exist on your computer, navigate to that directory via the command line and run the following command:

git clone https://github.com/sveltejs/template use-mapbox-gl-js-with-svelte

Then, in your command line, cd into the new directory use-mapbox-gl-js-with-svelte and run the following command:

npm install

This will install the dependencies that your app requires, creating the file package-lock.json and the folder node_modules.

You also need to install Mapbox GL JS in this project. In the same directory, run the following command:

npm install mapbox-gl

Finally, open the index.html file in the public folder in a text editor of your choice. Add the following CSS within the <head> of the document to make sure your app will use all the space available in the browser window:

<style>
body {
margin: 0;
padding: 0;
}
</style>

Setup is complete and you should have the following file structure:

folder

use-mapbox-gl-js-with-svelte

folder node_modules

folder public

code favicon.ico

code global.css

code index.html

folder scripts

code setupTypeScript.js

folder src

code App.svelte

code main.js

code .gitignore

code package-lock.json

code package.json

document README.md

code rollup.config.js

Save your changes.

Create the Svelte app

All the programming in this tutorial, including HTML, CSS, and JavaScript will occur in the src/App.svelte file. Open this file.

Set up the Svelte app

This app will include a Mapbox map, JavaScript to handle storing and updating information about the map, a <div> to show that information, and CSS to style the <div>. You should set up the bones of your app like this; we will handle the map itself later. Delete any HTML in App.svelte and replace it with the following:

<head> </head>

<script></script>

<div></div>

<style></style>

Add Mapbox GL JS

Add the following import statement between your <script> tags to import the Map object from Mapbox GL to your Svelte app:

import { Map } from 'mapbox-gl';

Add the following immediately below the line above to give your app access to Mapbox GL JS's CSS properties:

import '../node_modules/mapbox-gl/dist/mapbox-gl.css';

Add variables

To load a map on a webpage with Svelte, we will need to create some context for the map. Specifically, we need variables for the map, the HTML element that will contain the map, and the map's starting position (including longitude, latitude, and zoom level).

Add the following between your <script> tags, below your import statement:

let map;
let mapContainer;
let lng, lat, zoom;

lng = -71.224518;
lat = 42.213995;
zoom = 9;

These positional values will create a map centered near Boston, Massachusetts.

Use Svelte binding

Let's study the mapContainer variable for a moment. The Mapbox map needs certain contextual attributes defined immediately to work, such as the map's center and style. One such attribute is the map's container. This container is an <div> that the map renders in.

To do this, we will use Svelte binding. Between your empty <div> tags, insert the following:

<div class="map-wrap">
<div class="map" bind:this="{mapContainer}" />
</div>

This "binds" the variable mapContainer to the <div> with class "map". When the map is rendered on the page, this is where it will be.

Add map CSS

Now that there exists an HTML element with a class of map, we can apply CSS styling to that class. Between your empty <style> tags, add the following:

.map {
position: absolute;
width: 100%;
height: 100%;
}

Add Svelte lifecycle

You will import Svelte functions right below where you imported the Map object from Mapbox GL. On the next line, add:

import { onMount, onDestroy } from 'svelte';

onMount and onDestroy are Svelte lifecycle functions. onMount in particular runs after a component is first rendered to the DOM. The creation of the map should go in onMount.

Take note of your Mapbox access token, then add the following directly underneath your variable declarations and definitions:

onMount(() => {
const initialState = { lng: lng, lat: lat, zoom: zoom };

map = new Map({
container: mapContainer,
accessToken: <UserAccessToken />,
style: `mapbox://styles/mapbox/outdoors-v11`,
center: [initialState.lng, initialState.lat],
zoom: initialState.zoom
});
});

onDestroy(() => {
map.remove();
});

At this point, you've added enough code to load a Mapbox map in a Svelte app. Run npm run dev in your app's root directory to launch the development server, and you should see an interactive map of Boston.

Save your changes.

Display map information in UI

This app will need to be able to store and render the longitude, latitude, and zoom for the map in a UI element. These values will all change as your user interacts with the map, and the UI will update with it.

Add UI HTML

We need variables to store this information, but these variables (lng, lat, and zoom) are already created. It's time to add to the <div> tags that will become the informational sidebar UI element. Add the following HTML between your root <div> tags, above the <div> with class "map-wrap">:

<div class="sidebar">
Longitude: {lng.toFixed(4)} | Latitude: {lat.toFixed(4)} | Zoom:
{zoom.toFixed(2)}
</div>

Add sidebar CSS

If you run npm run dev at this point, you will see that the map's initial position and zoom are displayed above the map; The presentation is not styled and does not change when interacting with the map.

Before we work on updating the display with current data, we should style the display. Between your <style> tags, under the rules for the map class, add the following:

.sidebar {
background-color: rgb(35 55 75 / 90%);
color: #fff;
padding: 6px 12px;
font-family: monospace;
z-index: 1;
position: absolute;
top: 0;
left: 0;
margin: 12px;
border-radius: 4px;
}

Save your changes.

Update center and zoom information

Next, you need to create a function that stores the new latitude, longitude, and zoom that you get when a user interacts with the map. You will write Mapbox GL JS map.on() functions that reset the value of these variables when a user moves the map.

Create that function under zoom = 9; in your <script> tags:

function updateData() {
zoom = map.getZoom();
lng = map.getCenter().lng;
lat = map.getCenter().lat;
}

At this point, this function is never called. You must apply a Mapbox GL JS map.on() function with a 'move' event. In onMount(), under the map declaration, insert the following:

map.on('move', () => {
updateData();
});

Save your work.

Final product

You have created a Svelte app that uses Mapbox GL JS to render a map, display the center coordinates and the zoom level of the map, and then update that display when a user interacts with the map.

The final App.svelte page will look like the following:

<script>
import { onMount, onDestroy } from 'svelte';
import { Map } from 'mapbox-gl';
import '../node_modules/mapbox-gl/dist/mapbox-gl.css';

let map;
let mapContainer;
let lng, lat, zoom;

lng = -71.224518;
lat = 42.213995;
zoom = 9;

function updateData() {
zoom = map.getZoom();
lng = map.getCenter().lng;
lat = map.getCenter().lat;
}

onMount(() => {
const initialState = { lng: lng, lat: lat, zoom: zoom };

map = new Map({
container: mapContainer,
accessToken: <UserAccessToken />,
style: `mapbox://styles/mapbox/outdoors-v11`,
center: [initialState.lng, initialState.lat],
zoom: initialState.zoom
});

map.on('move', () => {
updateData();
});
});

onDestroy(() => {
map.remove();
});
</script>

<div>
<div class="sidebar">
Longitude: {lng.toFixed(4)} | Latitude: {lat.toFixed(4)} | Zoom:
{zoom.toFixed( 2 )}
</div>
<div class="map-wrap">
<div class="map" bind:this="{mapContainer}" />
</div>
</div>

<style>
.map {
position: absolute;
width: 100%;
height: 100%;
}

.sidebar {
background-color: rgb(35 55 75 / 90%);
color: #fff;
padding: 6px 12px;
font-family: monospace;
z-index: 1;
position: absolute;
top: 0;
left: 0;
margin: 12px;
border-radius: 4px;
}
</style>

Next steps

Now that you have created a Svelte app that uses Mapbox GL JS, you can explore examples using other JavaScript frameworks, such as React.

Was this page helpful?