MapSnippets logoMapSnippets logo

Style Expressions with MapLibre GL JS

MapLibre GL JS

Use MapLibre style expressions like interpolate and step to dynamically size and color features based on data properties.

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: [15, 50],
  zoom: 6
});
map.on('load', () => {
  const cities = { type: 'FeatureCollection', features: [
    { type: 'Feature', geometry: { type: 'Point', coordinates: [14.42, 50.08] }, properties: { name: 'Prague', pop: 1300 } },
    { type: 'Feature', geometry: { type: 'Point', coordinates: [16.61, 49.20] }, properties: { name: 'Brno', pop: 380 } },
    { type: 'Feature', geometry: { type: 'Point', coordinates: [18.26, 49.82] }, properties: { name: 'Ostrava', pop: 290 } },
    { type: 'Feature', geometry: { type: 'Point', coordinates: [15.05, 50.77] }, properties: { name: 'Liberec', pop: 105 } },
    { type: 'Feature', geometry: { type: 'Point', coordinates: [13.38, 49.74] }, properties: { name: 'Plzen', pop: 175 } }
  ] };
  map.addSource('cities', { type: 'geojson', data: cities });
  map.addLayer({ id: 'city-circles', type: 'circle', source: 'cities', paint: {
    'circle-radius': ['interpolate', ['linear'], ['get', 'pop'], 100, 6, 500, 14, 1300, 24],
    'circle-color': ['interpolate', ['linear'], ['get', 'pop'], 100, '#2196F3', 700, '#FF9800', 1300, '#F44336'],
    'circle-stroke-width': 2, 'circle-stroke-color': '#fff'
  } });
  map.addLayer({ id: 'city-labels', type: 'symbol', source: 'cities',
    layout: { 'text-field': ['get', 'name'], 'text-font': ['Noto Sans Regular'], 'text-size': 12, 'text-offset': [0, 1.5], 'text-anchor': 'top' },
    paint: { 'text-color': '#333', 'text-halo-color': '#fff', 'text-halo-width': 1 }
  });
});

How it works

MapLibre expressions let you drive visual properties from feature data at render time. The interpolate expression maps a numeric property to a continuous output range for both size and color.

In this example, city circles scale from 6px to 24px based on population, and change color from blue (small) through orange to red (large). All computation happens on the GPU, so thousands of features render efficiently.

The ['get', 'pop'] expression reads the pop property from each feature. Combined with ['interpolate', ['linear'], ...], it creates smooth transitions between defined stops.

Key APIs

API Description Docs
interpolate Smooth value mapping between stops maplibre.org docs
step Discrete value mapping at thresholds maplibre.org docs
case Conditional branching maplibre.org docs
match Value matching (like switch) maplibre.org docs

FAQ

What is the difference between interpolate and step?

interpolate produces smooth gradients between stops. step produces discrete jumps: the output stays constant until the next threshold.

Can I combine multiple expressions?

Yes. Nest expressions freely. For example, use case with get to conditionally choose between different interpolation scales.

Common mistakes

  • Mismatching the number of stops and outputs in interpolate: each input value needs a corresponding output
  • Using step when you want smooth transitions: step creates hard breaks between values
  • Forgetting that ['get', 'prop'] returns null for missing properties: use a fallback with coalesce
auto_awesome

Build maps using MapLibre GL JS with AI

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