MapSnippets logoMapSnippets logo

Polygons & Areas

Render filled polygon areas with custom stroke and fill styles Each library has its own approach: here's how they compare.

Quick Recommendations

Leaflet — A strong choice for simple filled areas where L.polygon with coordinate arrays and style options produces a polygon in one call.

MapLibre GL JS — A strong fit when polygons need data-driven fill colors, opacity expressions, or must layer with other vector tile data.

OpenLayers — Best when polygons need advanced geometry operations like union, intersection, or buffering with OpenLayers' geometry tools.

MapTiler SDK — Brings MapLibre's fill layer approach, with automatic basemap configuration.

At a Glance

LeafletMapLibreOpenLayersSDK
Coordinates[lat, lng][lng, lat]fromLonLat([lng, lat])[lng, lat]
RenderingDOM + Canvas (2D)WebGL (GPU, 60fps)Canvas + WebGLWebGL (GPU, 60fps)
Bundle size~42 KB gzipped~250 KB gzipped~290 KB gzipped (tree-shakeable)~280 KB gzipped (includes MapLibre)
Learning curveEasiest (simple API, great tutorials)Moderate (source/layer model, expressions)Steepest (projections, OGC standards, verbose API)Easy (MapLibre API with convenience helpers)
3D supportNo native 3D (2D only)Full: terrain, fill-extrusion, globe, skyLimited: WebGL layers, no native globeFull (same as MapLibre)
Code lines10222423

Code Snippets

Click a library to expand its code. Each snippet shows only the core logic: the scaffold handles HTML boilerplate.

Leaflet10 linesShow code
arrow_forwardFull example
const map = L.map('map').setView([48.86, 2.34], 14);
L.tileLayer('https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', {
  tileSize: 256,
  attribution: '&copy; <a href="https://www.maptiler.com/">MapTiler</a> &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);
const polygon = L.polygon([
  [48.8650, 2.3300], [48.8650, 2.3450],
  [48.8560, 2.3450], [48.8560, 2.3300]
], { color: '#FF5722', fillColor: '#FF5722', fillOpacity: 0.3, weight: 2 }).addTo(map);
polygon.bindPopup('Selected area');
MapLibre GL JS22 linesShow code
arrow_forwardFull example
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 }
  });
});
OpenLayers24 linesShow code
arrow_forwardFull example
var polygon = new ol.Feature({
  geometry: new ol.geom.Polygon([[
    ol.proj.fromLonLat([2.33, 48.87]),
    ol.proj.fromLonLat([2.37, 48.87]),
    ol.proj.fromLonLat([2.37, 48.85]),
    ol.proj.fromLonLat([2.33, 48.85]),
    ol.proj.fromLonLat([2.33, 48.87])
  ]])
});
var vectorLayer = new ol.layer.Vector({
  source: new ol.source.Vector({ features: [polygon] }),
  style: new ol.style.Style({
    fill: new ol.style.Fill({ color: 'rgba(230, 57, 70, 0.3)' }),
    stroke: new ol.style.Stroke({ color: '#e63946', width: 2 })
  })
});
var map = new ol.Map({
  target: 'map',
  layers: [
    new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://api.maptiler.com/maps/streets-v4/256/{z}/{x}/{y}.png?key=YOUR_MAPTILER_KEY', attributions: '&copy; <a href="https://www.maptiler.com/copyright/">MapTiler</a>' }) }),
    vectorLayer
  ],
  view: new ol.View({ center: ol.proj.fromLonLat([2.35, 48.86]), zoom: 14 })
});
MapTiler SDK23 linesShow code
arrow_forwardFull example
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
  container: 'map',
  style: maptilersdk.MapStyle.STREETS,
  center: [2.34, 48.86],
  zoom: 13
});
map.on('load', () => {
  map.addSource('area', {
    type: 'geojson',
    data: { type: 'Feature', geometry: { type: 'Polygon',
      coordinates: [[[2.32, 48.87], [2.36, 48.87], [2.36, 48.85], [2.32, 48.85], [2.32, 48.87]]]
    }}
  });
  map.addLayer({
    id: 'area-fill', type: 'fill', source: 'area',
    paint: { 'fill-color': '#9C27B0', 'fill-opacity': 0.4 }
  });
  map.addLayer({
    id: 'area-outline', type: 'line', source: 'area',
    paint: { 'line-color': '#9C27B0', 'line-width': 2 }
  });
});

Things to Know

Implementation-specific details that matter for polygons & areas.

Leaflet

L.polygon takes [lat, lng] arrays; fill and stroke are set via options (fillColor, fillOpacity, color, weight).

MapLibre GL JS

Polygon is a GeoJSON source + fill layer + optional line layer for the outline; fill-color and fill-opacity are paint properties.

OpenLayers

Polygon is an ol.Feature with ol.geom.Polygon; fill and stroke are separate ol.style objects composed into an ol.style.Style.

MapTiler SDK

Same GeoJSON source + fill/line layer pattern as MapLibre; SDK adds no polygon-specific convenience methods.

Which Library to Use?

auto_awesome

Build Maps with AI

Generate code like these examples using mapping library skills in your IDE.