MapLibre GL JS
MapLibre GL JS renders interactive vector maps in the browser using WebGL. It loads the Maptoolkit community style URL directly, with no API key.
Basic setup
npm
npm install maplibre-gl @maptoolkit/maplibre-logo-controlPackage names and the CSS import are resolved at build time, so these two files need a
bundler such as Vite, webpack or Parcel. Saved as a single .html file and opened in a
browser, they fail with Failed to resolve module specifier "maplibre-gl". For a file that
runs straight from disk, use the CDN setup below.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
margin: 0;
}
#map {
height: 100vh;
}
</style>
<title>MapLibre GL JS</title>
</head>
<body>
<div id="map"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>src/main.js
import * as maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { LogoControl } from '@maptoolkit/maplibre-logo-control';
import '@maptoolkit/maplibre-logo-control/style.css';
const map = new maplibregl.Map({
container: 'map',
style: 'https://styles.maptoolkit.org/summer.json',
center: [16.37, 48.21],
zoom: 12,
attributionControl: {compact: false}
});
map.addControl(new LogoControl());The index.html looks incomplete on purpose. It has no <script> for MapLibre and no
<link> for any stylesheet, because the bundler adds both. src/main.js imports the library
and the two CSS files, and the build rewrites the page: Vite, for instance, turns that one
<script type="module" src="/src/main.js"> into a hashed script tag plus a <link> for the
bundled CSS. Opening the index.html as it stands in a browser gives you a blank page, which
is expected; run the build and open what it produces.
MapLibre GL JS v6 publishes named exports and no default export, so the import is
import * as maplibregl. Written as import maplibregl from 'maplibre-gl' the binding is
undefined and new maplibregl.Map() throws.
The logo’s stylesheet is a separate import. @maptoolkit/maplibre-logo-control draws the
logo as a CSS background, so without @maptoolkit/maplibre-logo-control/style.css the
control is added to the map and renders as an empty box.
CDN
import * as maplibregl from 'https://cdn.jsdelivr.net/npm/maplibre-gl@6.9.0/dist/maplibre-gl.mjs';
const map = new maplibregl.Map({
container: 'map',
style: 'https://styles.maptoolkit.org/summer.json',
center: [16.37, 48.21],
zoom: 12,
attributionControl: {compact: false}
});<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@6.9.0/dist/maplibre-gl.css">
<style>
body {
margin: 0;
}
#map {
height: 100vh;
}
#maptoolkit-attribution img {
display: block;
height: 100%;
}
#maptoolkit-attribution {
position: absolute;
height: 24px;
bottom: 8px;
left: 8px;
}
</style>
<title>MapLibre GL JS</title>
</head>
<body>
<div id="map"></div>
<a id="maptoolkit-attribution" href="https://www.maptoolkit.org/" target="_blank" rel="noopener"><img src="https://www.maptoolkit.org/assets/maptoolkit-attribution.png" alt="Maptoolkit"></a>
<script type="module">
import * as maplibregl from 'https://cdn.jsdelivr.net/npm/maplibre-gl@6.9.0/dist/maplibre-gl.mjs';
const map = new maplibregl.Map({
container: 'map',
style: 'https://styles.maptoolkit.org/summer.json',
center: [16.37, 48.21],
zoom: 12,
attributionControl: {compact: false}
});
</script>
</body>
</html>Examples
See the Examples gallery for ready-to-run snippets covering markers, popups, GeoJSON data, layer styling, camera animation, and more.
Attribution
Keep the Maptoolkit logo with @maptoolkit/maplibre-logo-control and the © Maptoolkit © Openstreetmap copyright line visible. See Attribution for the full requirements.