Add a custom control declarative way
Declarative controls offer a simple way to add interactive UI elements to the map by using HTML attributes alone. Instead of instantiating controls through JavaScript, developers annotate DOM elements and allow the SDK to discover and wire them automatically.
To activate declarative control detection set the customControls option to true in the map initialization configuration. Alternatively, customControls may be set to a CSS selector string, restricting autodetection to:
- Elements matching the selector directly
- Or elements whose ancestor matches the selector
NPM module setup
npm install --save @maptiler/sdk bootstrap
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import 'bootstrap/dist/css/bootstrap.min.css';
config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const map = new Map({
container: 'map', // container's id or the HTML element to render the map
style: MapStyle.STREETS,
customControls: true,
navigationControl: false,
geolocateControl: false,
terrainExaggeration: 4,
});
//custom control (center map)
document.querySelector(".home-button")?.addEventListener("click", () => map.easeTo({ center: [15, 50], zoom: 7 }));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex">
<title>Add a custom control declarative way | NPM example</title>
<link rel="stylesheet" href="./style.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:FILL@0..1">
</head>
<body>
<div id="map"></div>
<div data-maptiler-control-group class="btn-group-vertical m-2">
<button data-maptiler-control="zoom-in" class="btn btn-light">
<span class="material-symbols-outlined">zoom_in</span>
</button>
<button data-maptiler-control="zoom-out" class="btn btn-light">
<span class="material-symbols-outlined">zoom_out</span>
</button>
<button data-maptiler-control="reset-view" class="btn btn-light">
<span class="material-symbols-outlined">navigation</span>
</button>
</div>
<button data-maptiler-control="toggle-projection" data-maptiler-position="top-left" class="btn btn-primary m-2">
<span class="material-symbols-outlined"></span>
</button>
<button data-maptiler-control="toggle-terrain" data-maptiler-position="top-left" class="btn btn-success m-2">
<span class="material-symbols-outlined">terrain</span>
</button>
<button data-maptiler-control data-maptiler-position="bottom-left" class="btn btn-danger m-2 float-end home-button">
<span class="material-symbols-outlined">home</span>
</button>
<script type="module" src="./main.js"></script>
</body>
</html>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
.maplibregl-control-container .btn {
pointer-events: auto;
display: block;
}
[data-maptiler-control="reset-view"] span {
transform: rotateX(calc(var(--maptiler-pitch) * 1deg))
rotateZ(calc(var(--maptiler-bearing) * -1deg));
}
[data-maptiler-control="toggle-projection"] span::after {
content: "globe";
}
@container style(--maptiler-is-globe-projection: true) {
[data-maptiler-control="toggle-projection"] span::after {
content: "map";
}
}
[data-maptiler-control="toggle-terrain"] span, .home-button span {
transition: font-variation-settings 1s ease-in-out;
font-variation-settings: 'FILL' 0;
}
@container style(--maptiler-has-terrain: true) {
[data-maptiler-control="toggle-terrain"] span {
font-variation-settings: 'FILL' 1;
}
}
@container style(--maptiler-center-lng: 15) and style(--maptiler-center-lat: 50) {
.home-button span {
font-variation-settings: 'FILL' 1;
}
}
Learn more
Check out the MaptilerExternalControl API reference to learn all the options to add custom controls to your map interface.
Related examples
Custom control programmatically
ExamplesProgrammatically add custom controls for dynamic map logic integration.