Vector maps for web

Vector tiles are the best way to get maps on your website. They offer the best experience for you users because they look great at any zoom level on any screen (Apple retina displays, for example). They also allow for dynamic applications with adaptive styling based on real-time data.

Displaying a map

Our vector maps are compatible with any rendering library capable of rendering Mapbox Vector Tiles. Below is an example of typical usage. The important piece is the style URL. See our style library for additional options.

NOTE: Mapbox GL JS v2 is no longer free open source software and requires an active commercial license and subscription agreement with Mapbox. However, v1.x is still free and open. Stadia Maps is actively working to build consensus towards a community-driven, fully-open and free fork of Mapbox GL JS v1, and we will continue to support and collaborate on these efforts going forward under the MapLibre project.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Vector Map Demo</title>
        <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
        <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/mapbox-gl/1.13.0/mapbox-gl.js"></script>
        <link href="//cdnjs.cloudflare.com/ajax/libs/mapbox-gl/1.13.0/mapbox-gl.css" rel="stylesheet" />
        <style type="text/css">
            body {
              margin: 0;
              padding: 0;
            }

            #map {
              position: absolute;
              top: 0;
              bottom: 0;
              width: 100%;
            }
        </style>
    </head>
    <body>
        <div id="map"></div>
        <script type="text/javascript">
         var map = new mapboxgl.Map({
           container: 'map',
           style: 'https://tiles.stadiamaps.com/styles/alidade_smooth.json',  // Style URL; see our documentation for more options
           center: [12, 53],  // Initial focus coordinate
           zoom: 4
         });

         // Mapbox GL JS has a bug in it's handling of RTL, so we have to grab this dependency as well until they
         // combine it with the main library
         mapboxgl.setRTLTextPlugin('https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.1/mapbox-gl-rtl-text.js');

         // Add zoom and rotation controls to the map.
         map.addControl(new mapboxgl.NavigationControl());
        </script>
    </body>
</html>

Adding markers to the map

Once you have a map, you probably want to add some markers to it! The example below can serve as a starting point, and covers all the main points. You can easily substitute your own branded markers, style the popup (or remove it), etc. Please refer to the Mapbox documentation for additional details.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Vector Map Demo</title>
        <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
        <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/mapbox-gl/1.13.0/mapbox-gl.js"></script>
        <link href="//cdnjs.cloudflare.com/ajax/libs/mapbox-gl/1.13.0/mapbox-gl.css" rel="stylesheet" />
        <style type="text/css">
        body {
            margin: 0;
            padding: 0;
        }

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

        /* We recommend using an icon that is 2x the intended display size, so that it renders nicely on retina displays. */
        .marker {
            /* The following icon is owned by Stadia Maps. While you maintain an account with us, we grant you royalty-free use of
             * this image when displayed on our maps.
             */
            background-image: url('data:image/png;base64,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');
            background-size: cover;
            width: 27px;
            height: 42px;
            cursor: pointer;
        }
        </style>
    </head>
    <body>
        <div id="map"></div>
        <script type="text/javascript">
        var map = new mapboxgl.Map({
            container: 'map',
            style: 'https://tiles.stadiamaps.com/styles/alidade_smooth.json',  // Style URL; see our documentation for more options
            center: [6.942373, 50.332852],  // Initial focus coordinate (long, lat)
            zoom: 14
        });

        // Add zoom and rotation controls to the map.
        map.addControl(new mapboxgl.NavigationControl());

        // First, we define our marker locations. You can use whatever format you want when
        // working with custom markers, but we have chosen to use GeoJSON for this example, as
        // a lot of geospatial data comes in this form. If you have a lot of data, you may want to
        // put it in another file that is loaded separately.
        var markerCollection = {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "geometry": {
                    "type": "Point",
                    // NOTE: in GeoJSON notation, LONGITUDE comes first. GeoJSON
                    // uses x, y coordinate notation, just like you used to describe
                    // graph coordinates in high school. What you may not realize is
                    // that latitude, often said first in English, is actually the y axis. 
                    "coordinates": [6.940046, 50.333947]
                },
                "properties": {
                    "title": "Nürburgring"
                }
            }]
        };

        // Next, we can add markers to the map
        markerCollection.features.forEach(function(point) {
            // Since these are HTML markers, we create a DOM element first, which we will later
            // pass to the Marker constructor.
            var elem = document.createElement('div');
            elem.className = 'marker';

            // Now, we construct a marker and set it's coordinates from the GeoJSON. Note the coordinate order.
            var marker = new mapboxgl.Marker(elem);
            marker.setLngLat(point.geometry.coordinates);

            // You can also create a popup that gets shown when you click on a marker. You can style this using
            // CSS as well if you so desire. A minimal example is shown. The offset will depend on the height of your image.
            var popup = new mapboxgl.Popup({ offset: 24, closeButton: false });
            popup.setHTML('<div>' + point.properties.title + '</div>');

            // Set the marker's popup.
            marker.setPopup(popup);

            // Finally, we add the marker to the map.
            marker.addTo(map);
        });
        </script>
    </body>
</html>

Alternative renderers

Stadia Maps serves tiles that conform to the MVT specification, which means you have the option of using any renderer that supports the MVT format, not just Mapbox GL JS. OpenLayers and Tangram are the most common alternates. Both have powerful features and long histories of their own.

Stadia Maps will always support your rights to use any library that you choose. While we aren't quite ready to distribute styles with our stamp of quality, we are actively working toward official styles for other renderers like OpenLayers and Tangram.

OpenLayers

You can use any (schema-compatible) Mapbox GL JSON style with OpenLayers using ol-mapbox-style. This library will attempt to convert a Mapbox GL JSON stylesheet into an OpenLayers one. You’ll notice there are a few differences between the OpenLayers version and the Mapbox GL rendering, but it is close enough if you want to leverage the power of OpenLayers with Stadia Maps vector tiles.

<!DOCTYPE html>
<html>
    <head>
        <title>OpenLayers Vector Tile Demo</title>
        <!-- Note that fonts will not perfectly match our Mapbox GL styles at present -->
        <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans" />
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css">
        <style>
            html, body {
                height: 100%;
                margin: 0;
            }
            #map {
                width: 100%;
                height: 100%;
                background-color: #f8f4f0;
            }
        </style>
    </head>
    <body>
        <div id="map"></div>
        <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,Promise"></script>
        <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script>
        <script src="https://unpkg.com/ol-mapbox-style@6.2.1/dist/olms.js"></script>
        <script>
            olms('map', 'https://tiles.stadiamaps.com/styles/alidade_smooth_dark.json').then(function(map) {
                // Callback to configure the map if necessary
            });
        </script>
    </body>
</html>

Tangram

Tangram offers a number of unique features compared to other vector renderers, including custom GLSL shaders, unique 3D rendering customizations, and custom camera and lighting controls. We don't yet offer official styles, but are working on a tool that enables easy migration so we can do so in the future. You can follow the development of our open-source Cartogrify project on GitHub.

Further reading

For more details on Mapbox GL JS, check out the official documentation for more information.

You can also check out the OpenLayers and Tangram projects for alternative vector tile renderers.