3D Building Extrusions
Add 3D extruded buildings from vector tile data using fill-extrusion layers Each library has its own approach: here's how they compare.
Quick Recommendations
MapLibre GL JS — Best when you need full control over fill-extrusion paint properties, light direction, and data-driven height expressions.
MapTiler SDK — For MapTiler SDK users, this means MapLibre's fill-extrusion layers plus automatic access to MapTiler building data.
At a Glance
| MapLibre | SDK | |
|---|---|---|
| Coordinates | [lng, lat] | [lng, lat] |
| Rendering | WebGL (GPU, 60fps) | WebGL (GPU, 60fps) |
| Bundle size | ~250 KB gzipped | ~280 KB gzipped (includes MapLibre) |
| Learning curve | Moderate (source/layer model, expressions) | Easy (MapLibre API with convenience helpers) |
| 3D support | Full: terrain, fill-extrusion, globe, sky | Full (same as MapLibre) |
| Code lines | 35 | 35 |
Code Snippets
Click a library to expand its code. Each snippet shows only the core logic: the scaffold handles HTML boilerplate.
MapLibre GL JS35 linesShow code
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/streets-v4/style.json?key=YOUR_MAPTILER_KEY',
center: [14.4205, 50.0875],
zoom: 16,
pitch: 55,
bearing: -20,
canvasContextAttributes: { antialias: true }
});
map.addControl(new maplibregl.NavigationControl());
map.on('load', () => {
const style = map.getStyle();
const vectorSrc = Object.keys(style.sources).find(k => style.sources[k].type === 'vector');
if (!vectorSrc) return;
// Insert the 3D layer BEFORE the first label layer so labels stay on top.
const labelLayerId = style.layers.find(l => l.type === 'symbol' && l.layout && l.layout['text-field'])?.id;
map.addLayer({
id: '3d-buildings',
source: vectorSrc,
'source-layer': 'building',
type: 'fill-extrusion',
minzoom: 14,
filter: ['!=', ['get', 'hide_3d'], true],
paint: {
'fill-extrusion-color': '#aaa',
'fill-extrusion-height': [
'interpolate', ['linear'], ['zoom'],
14, 0,
16, ['coalesce', ['get', 'render_height'], 0]
],
'fill-extrusion-base': ['coalesce', ['get', 'render_min_height'], 0],
'fill-extrusion-opacity': 0.7
}
}, labelLayerId);
});MapTiler SDK35 linesShow code
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
container: 'map',
style: maptilersdk.MapStyle.STREETS,
center: [2.3488, 48.8534],
zoom: 15.5,
pitch: 60,
bearing: -17,
canvasContextAttributes: { antialias: true }
});
map.on('load', () => {
const style = map.getStyle();
const src = Object.keys(style.sources).find(s => map.getSource(s).type === 'vector');
if (!src) return;
// Insert above basemap but below labels so labels stay on top.
const labelLayerId = style.layers.find(l => l.type === 'symbol' && l.layout && l.layout['text-field'])?.id;
map.addLayer({
id: 'buildings-3d',
type: 'fill-extrusion',
source: src,
'source-layer': 'building',
minzoom: 14,
filter: ['!=', ['get', 'hide_3d'], true],
paint: {
'fill-extrusion-color': '#9C27B0',
'fill-extrusion-height': [
'interpolate', ['linear'], ['zoom'],
14, 0,
16, ['coalesce', ['get', 'render_height'], 0]
],
'fill-extrusion-base': ['coalesce', ['get', 'render_min_height'], 0],
'fill-extrusion-opacity': 0.8
}
}, labelLayerId);
});Things to Know
Implementation-specific details that matter for 3d building extrusions.
Fill-extrusion layers read height from vector tile properties; light settings (anchor, color, intensity) control the 3D appearance.
Identical fill-extrusion configuration to MapLibre; the SDK provides no extra 3D building helpers.
Which Library to Use?
Add 3D extruded buildings from MapTiler vector tiles using fill-extrusion layers.
Best when you need full control over fill-extrusion paint properties, light direction, and data-driven height expressions.
Add 3D building height extrusions using a fill-extrusion layer from the vector tile source.
For MapTiler SDK users, this means MapLibre's fill-extrusion layers plus automatic access to MapTiler building data.
Build Maps with AI
Generate code like these examples using mapping library skills in your IDE.