MapSnippets logoMapSnippets logo

Fill Layers with MapLibre GL JS

MapLibre GL JS

Render a filled polygon area using a GeoJSON source and a fill layer -- the MapLibre way to draw polygons on the map.

progress_activityLoading map...
const map = new maplibregl.Map({
  container: 'map',
  style: 'https://api.maptiler.com/maps/streets-v4/style.json?key=YOUR_MAPTILER_KEY',
  center: [14.42, 50.08],
  zoom: 12
});
map.on('load', () => {
  map.addSource('area', {
    type: 'geojson',
    data: { type: 'Feature', geometry: { type: 'Polygon',
      coordinates: [[[14.39, 50.10], [14.45, 50.10], [14.45, 50.06], [14.39, 50.06], [14.39, 50.10]]] } }
  });
  const labels = map.getStyle().layers.find(l => l.type === 'symbol' && /label/.test(l.id));
  map.addLayer({
    id: 'area-fill', type: 'fill', source: 'area',
    paint: { 'fill-color': '#6366f1', 'fill-opacity': 0.3 }
  }, labels ? labels.id : undefined);
  map.addLayer({
    id: 'area-outline', type: 'line', source: 'area',
    paint: { 'line-color': '#6366f1', 'line-width': 2 }
  });
});

How it works

A GeoJSON polygon requires a closed ring: the first and last coordinate must be identical. Add it as a source and render with a fill layer for the interior and a line layer for the border.

The third parameter of addLayer() is beforeId, which inserts the layer below a specific existing layer. This example finds the first label layer and inserts the polygon beneath it so place names remain visible.

Setting fill-opacity below 1.0 makes the polygon semi-transparent, allowing the base map to show through.

Key APIs

API Description Docs
fill layer type Render filled polygon areas maplibre.org docs
addLayer(layer, beforeId) Insert layer before another maplibre.org docs
fill-pattern Fill polygon with a repeating image maplibre.org docs

FAQ

Why does my polygon cover the map labels?

Use the beforeId parameter to insert the fill layer below the first symbol/label layer in the style.

How do I make a polygon with a hole?

Add a second ring to the coordinates array. The first ring is the outer boundary, subsequent rings are holes.

Common mistakes

  • Not closing the polygon ring: the first and last coordinate must match
  • Hardcoding label layer IDs for beforeId: detect them at runtime since they vary by style
  • Using [lat, lng] order instead of [lng, lat] for polygon coordinates
auto_awesome

Build maps using MapLibre GL JS with AI

Generate code like this fill layers with maplibre gl js example using the MapLibre GL JS skill in your IDE.