Style Specification Support
BasemapLayer implements a subset of the MapLibre Style Specification. This page lists
the parts of the specification and what the module currently does with each. Properties that are
not listed are not supported. Follow-up changes update the table as gaps close.
| Status | Meaning |
|---|---|
| Supported | Implemented as the specification describes, apart from the notes. |
| Partial | Implemented with a documented approximation, or for some of the values. |
| Not supported | Ignored, so a style that uses it renders without it, unless a note says otherwise. |
Layer types
See Layers. Layers of an unsupported type are skipped.
| Layer type | Status | Notes |
|---|---|---|
background | Partial | background-color and background-opacity. background-pattern is not drawn and, as in the specification, disables background-color, so a patterned background draws nothing. |
fill | Partial | See Paint properties. |
line | Partial | See Paint properties and Layout properties. |
symbol | Partial | Text and icons at anchor points: one per point, line and polygon. See Symbols. |
fill-extrusion | Partial | Patterns, translation and the style's light are not supported. See Paint properties. |
raster | Partial | Inline tiles, or a TileJSON url. The style's own source properties take precedence over the TileJSON's, and only the TileJSON's tiles, minzoom, maxzoom, attribution, bounds, scheme, tileSize and encoding are used. scheme: "tms" and bounds are not applied. If the TileJSON cannot be fetched, is invalid or lists no tiles, a warning is logged and the source falls back to its own tiles; without them, its layers are skipped. |
circle | Partial | Points and multipoints of vector sources; circles are not drawn at line and polygon vertices. On a globe, a circle near a tile edge can draw twice, once from each overlapping tile. See Paint properties and Layout properties. |
heatmap | Not supported | |
hillshade | Not supported | |
color-relief | Not supported |
Sources
See Sources.
| Source type | Status | Notes |
|---|---|---|
vector | Partial | Inline tiles, or a TileJSON url. The style's own source properties take precedence over the TileJSON's, and only the TileJSON's tiles, minzoom, maxzoom, attribution, bounds, scheme, tileSize and encoding are used. scheme: "tms" and bounds are not applied. If the TileJSON cannot be fetched, is invalid or lists no tiles, a warning is logged and the source falls back to its own tiles; without them, its layers are skipped. |
raster | Partial | Inline tiles, or a TileJSON url. The style's own source properties take precedence over the TileJSON's, and only the TileJSON's tiles, minzoom, maxzoom, attribution, bounds, scheme, tileSize and encoding are used. scheme: "tms" and bounds are not applied. If the TileJSON cannot be fetched, is invalid or lists no tiles, a warning is logged and the source falls back to its own tiles; without them, its layers are skipped. |
raster-dem | Not supported | Its url is not fetched, and its layers are skipped. |
geojson | Not supported | Layers that use a GeoJSON source are skipped. |
image | Not supported | Its url is not fetched, and its layers are skipped. |
video | Not supported | Its url is not fetched, and its layers are skipped. |
Expressions and filters
See Expressions.
| Feature | Status | Notes |
|---|---|---|
| Constant and data-driven values | Supported | Evaluated with @maplibre/maplibre-gl-style-spec, per feature where the property allows it. |
| Zoom-dependent values | Partial | Evaluated at the zoom rounded down to a 0.25 step, not interpolated continuously. |
feature-state | Not supported | Feature state is always empty. |
filter | Supported | Evaluated per feature. ["zoom"] in a filter uses the integer zoom, as the specification says. |
Legacy ref layers | Supported | Resolved when the style loads. |
Layer visibility and zoom range
| Feature | Status | Notes |
|---|---|---|
minzoom / maxzoom | Supported | Compared with the exact zoom. |
Overzoom past source maxzoom | Supported | The deepest tiles are scaled up; layers keep drawing. |
layout.visibility | Supported | A layer with visibility: "none" is not drawn. To change it, pass a new style object, as for other style edits. |
Paint properties
See Layers for the properties of each type.
| Property | Status | Notes |
|---|---|---|
fill-color, fill-opacity | Supported | Per feature. On a globe, fills are drawn opaque. A fill-pattern disables fill-color, as in the specification. |
fill-outline-color | Partial | A 1 CSS pixel outline; MapLibre's is one device pixel. Not drawn when fill-antialias is false. |
fill-pattern | Partial | Per feature, with fill-opacity (also on a globe). Switches at integer zooms without cross-fading. WebGPU draws none. |
fill-translate, fill-translate-anchor | Partial | Moves the fill and its outline; on a globe, not its pattern. WebGL only; WebGPU draws fills untranslated. |
line-color, line-opacity, line-width | Supported | Per feature. |
line-dasharray | Partial | One dash and one gap per period; longer patterns merge their dashes. Switches at integer zooms instead of cross-fading. |
line-offset, line-gap-width | Partial | Per feature. Sharp corners break open on the outside, and a gap's two lines end apart instead of capped together. |
line-blur | Partial | Per feature, except with both line-dasharray and line-offset or line-gap-width, where a per-feature blur draws sharp. With a per-feature line-offset, where line-blur is more than half of line-gap-width the two lines of the gap overlap and draw their fades twice, darker than MapLibre. WebGL only; on WebGPU lines draw without blur, and the two lines of a gap line-blur pixels wider. |
line-gradient, line-pattern, line-translate | Not supported | |
fill-extrusion-color, -height, -base | Supported | Per feature, heights in meters. The alpha of the color is ignored, as in MapLibre. |
fill-extrusion-opacity | Partial | Applied to each surface, so walls behind a building can show through. |
fill-extrusion-pattern, -translate, -vertical-gradient | Not supported | Extrusions use deck.gl's default lighting, not the style's light. |
raster-opacity | Supported | While tiles load, a translucent layer can briefly show its lower-zoom placeholder tiles through the new ones. |
raster-brightness-min, -max | Supported | MapLibre's formulas. WebGL only. |
raster-saturation, -contrast, -hue-rotate | Supported | MapLibre's formulas. WebGL only. |
raster-resampling, resampling | Supported | nearest magnifies with the nearest texel and minifies linearly, as in MapLibre. |
raster-fade-duration | Not supported | Tiles appear without fading in. |
circle-radius, circle-color, circle-opacity | Supported | Per feature. |
circle-stroke-width, -color, -opacity | Supported | Per feature. The stroke is drawn outside circle-radius, as in MapLibre. |
circle-blur | Partial | Per feature. WebGL only; WebGPU draws without blur. The edge between fill and stroke stays sharp. |
circle-translate | Partial | circle-translate-anchor is not read: with viewport alignment the offset does not turn with the bearing. |
circle-pitch-alignment | Partial | On a globe, circles always face the viewer. |
circle-pitch-scale | Partial | Circles shrink with distance under pitch, as with map, the default; viewport is ignored. |
Layout properties
| Property | Status | Notes |
|---|---|---|
line-cap, line-join | Partial | Per feature. deck.gl has no square cap or bevel join: square caps are drawn as butt, so a zero-length dash draws nothing where MapLibre draws a square, and bevel joins are cut flat half the line width from the vertex. |
line-miter-limit | Partial | Per feature. A miter beyond the limit is cut flat at the limit rather than bevelled. |
symbol-*, text-*, icon-* | See Symbols | |
circle-sort-key | Partial | Orders the circles within a tile. Tiles draw one after another, so circles in different tiles are not ordered by key. |
| Other properties | Not supported | For example line-sort-key, fill-sort-key, line-round-limit, text-radial-offset, text-writing-mode, symbol-avoid-edges, symbol-z-order, the *-translate and *-pitch-alignment properties, text-rotation-alignment for point placement and icon-halo-*. |
Symbols
| Feature | Status | Notes |
|---|---|---|
symbol-placement: point | Partial | Points are labelled at the point, and each polygon at its pole of inaccessibility, as in MapLibre. Line features are labelled at the middle vertex of their first part. A polygon in two tiles' buffers is labelled by the tile that holds its pole. Polygon label search is bounded per tile; on a tile with unusually heavy polygon geometry, the remaining polygons are not labelled. |
symbol-placement: line / line-center | Partial | Symbols are placed along line features as in MapLibre: line repeats them every symbol-spacing pixels, line-center places one at the middle of the line by length. With line, features with the same text whose ends meet are joined first, and a label within half a symbol-spacing of an earlier one with the same text on the tile is dropped. A placement is skipped where the symbol does not fit on the line or, for text, where the line bends more than text-max-angle under it. The symbol's length is the longer of its icon and its text, measured in the label font at the text-size of zoom 18 (estimated from the character count while the font loads). Text and icons with *-rotation-alignment: map (or auto) are turned to the line's direction and drawn flat on the map; text is kept upright (text-keep-upright), and icons add icon-rotate. With viewport they stay upright billboards. The text itself is straight: it does not curve with the line. Placement uses the tile's zoom, so symbols do not move while zooming within a tile. Placement work is bounded per tile; on a tile with unusually heavy line geometry, the remaining symbols are not placed. text-offset is not turned with the label; on a steep line, an offset larger than half the label's length can leave the label's collision box off its anchor, so the label stays hidden. Polygon features are not labelled. |
text-field | Supported | Expressions and legacy {token} strings. |
text-color, text-opacity | Supported | Per feature. |
text-size | Supported | Per feature. A size of 0 hides the label. |
text-offset, text-anchor | Supported | Per feature. |
text-font | Partial | Mapped to a CSS font family list, weight and style; no glyphs are loaded. One font per style layer and zoom step. See Label fonts. |
text-halo-color, text-halo-width | Partial | Per feature. Drawn around the glyphs, at most a quarter of the text size wide, as in MapLibre. Widths are rounded to 0.25 px. Each distinct halo in a tile is drawn by its own text sublayer, for at most 8 halos per tile and style layer: the most common ones. Labels with any other halo get the most common halo; labels without a halo never get one. The halo's outline width depends on the text size, so each data-driven text-size value also needs its own halo; past the cap, a label drawn with another size's halo is off by the ratio of the two text sizes. Where labels with different halos overlap, they stack by sublayer rather than in label order. Translucent text (a text-color alpha or text-opacity below 1, or a label fading in or out) is drawn twice inside the glyph, so a halo makes it more opaque: an alpha of 0.5 draws as 0.75. MapLibre draws the halo under the glyph instead. All labels, with or without a halo, use a signed distance field font atlas with an 18 px buffer around each 64 px glyph: the atlas holds about half as many glyphs as a plain one within the GPU's texture size limit (about 1,600 distinct ideographs per font at 16,384 px), and each glyph's collision footprint includes the buffer, about 0.28 em beyond the glyph. |
text-halo-blur | Partial | Per feature, rounded to 0.25 px. As in MapLibre, the halo edge fades over 1.19 * blur px on each side. Each distinct blur in a tile needs its own halo, within the same cap of 8. The fade ends where the glyph distance field ends, about 0.28 of the text size past the glyph. WebGL only; WebGPU draws a sharp halo. |
text-max-width | Supported | Per feature, for symbol-placement: point. Lines are balanced and broken at spaces, hyphens and between ideographs, as in MapLibre; a word longer than the width is not broken. Widths are measured with the browser font rather than MapLibre glyph metrics, so breaks can differ slightly. Labels over 256 characters, or past a per-tile work budget, are not wrapped. |
text-line-height | Supported | One value per style layer and zoom step, as in the style spec. |
text-transform | Supported | Per feature. |
text-justify | Supported | Per feature. auto follows text-anchor. The default, center, centers the lines of a left- or right-anchored label within it, as in MapLibre. Labels along lines are centered. |
text-letter-spacing | Supported | Per feature. Added after each character but the last of a line, so the label and its collision box widen; counted in text-max-width line breaking and in the length of labels along lines, as in MapLibre. Text in a cursive script, such as Arabic, is not spaced, as in MapLibre. |
text-rotate, text-variable-anchor | Not supported | |
symbol-sort-key | Supported | Orders labels within a style layer. Later symbol layers in the style take priority over earlier ones. Without a sort key, labels are ranked by a built-in heuristic on OpenMapTiles fields (capital, class, water names), which MapLibre does not do. |
| Label collision | Partial | Labels are hidden where they collide, using deck.gl's CollisionFilterExtension, which tests an area around each label's anchor rather than its full box. Of two colliding labels with equal priority in one tile, the first one wins, as in MapLibre. |
text-allow-overlap, text-ignore-placement, text-optional, text-overlap | Partial | A symbol's text and icon share one collision test at its anchor, so a part is shown without its optional partner only when that part allows overlap. text-overlap: cooperative is treated as never. A part that ignores placement, and each symbol of an icon-only layer, still mark a box of 4 pixels on each side of the anchor, whatever the text-offset, which can hide a lower-priority symbol anchored there; MapLibre blocks nothing in that case. |
text-padding | Partial | At the stepped zoom. Widens each label's collision box by that many pixels on each side, so the label also hides the lower-priority symbols anchored within the padding. The collision test samples each symbol at its anchor, so only the padding of the symbol that hides counts; MapLibre keeps the two padded boxes apart. Between symbols of equal priority, the padding hides a label only where the label's own glyphs do not cover its anchor. |
icon-image | Supported | Expressions and legacy {token} names, from the style's sprites. |
icon-size, icon-opacity, icon-anchor, icon-offset | Supported | Per feature. |
icon-color | Supported | For SDF images. |
| Icon collision | Partial | Icons collide with labels and with each other, and an icon and its text are placed or hidden as one unit, in the same anchor-based test as labels. The whole icon box collides. As in MapLibre, a symbol whose text is empty, or whose icon is empty or missing from the sprites, follows the placement rules of its one part. |
icon-allow-overlap, icon-ignore-placement, icon-optional, icon-overlap | Partial | As for the text-* properties above. |
icon-rotate | Supported | Per feature, clockwise; along lines, added to the line's direction. As in MapLibre, the icon turns about its anchor point, with its icon-anchor and icon-offset. The icon collides with its turned box, where MapLibre uses the axis-aligned box around it. |
icon-rotation-alignment | Partial | map, or auto along lines: the icon is drawn flat on the map and turns with it, and along lines it is turned to the line's direction. viewport, or auto at points: the icon is a billboard, turned only by icon-rotate. icon-pitch-alignment is not read: an icon lies flat exactly when it turns with the map. On a globe, icons are always billboards, turned on screen. |
icon-padding | Partial | Per feature, one to four values. Widens each icon's collision box, so the icon also hides the lower-priority symbols anchored within the padding; only the padding of the symbol that hides counts, as for text-padding. The boxes are scaled with one factor per sprite and style layer in a tile, set for the tile's median icon; other icons are padded in proportion to their size. Both axes grow by the larger of the horizontal and vertical padding, split evenly between the two sides. |
icon-text-fit | Not supported |
Style resources
| Feature | Status | Notes |
|---|---|---|
sprite | Supported | A single URL or the array form. @2x is requested first when the device pixel ratio is above 1, as in MapLibre. URLs may carry query strings. |
glyphs | Not supported | Labels use browser fonts (see text-font). |
light | Not supported | |
sky, terrain | Not supported | |
projection | Not supported | Use deck.gl's MapView or GlobeView, with the mode prop. |
Rendering
| Feature | Status | Notes |
|---|---|---|
| Draw order | Partial | Style layers draw in style order across sources and tiles, as in MapLibre: each layer draws in every tile before the next, so a tile's fills do not cover a neighbouring tile's labels. A vector source split by another source's layers draws as one tile layer per run, and the runs share one cache of decoded tiles per source. A flat layer after a fill-extrusion layer is hidden behind the buildings. |
| Globe view | Partial | mode: 'globe' draws on deck.gl's GlobeView, with an optional atmosphere (see the globe prop). Labels and icons whose anchor is beyond the globe's horizon are hidden, on WebGL only; they disappear at once, where MapLibre GL JS fades them out. |