Painting
Ops that consume Features and put pixels on a canvas — flat fills, scatter dabs, brush strokes, stamps, text.
12 ops: brush-file, circles, fill-dabs, fill-solid, label-placement, line, line-stamp, stamp, stroke, text, text-draw, text-labels.
Ops with no demo image below produce no visible result on their own — they feed other nodes rather than paint.
brush-file
Section titled “brush-file”Brush source. src is an @asset ref or a literal path/name resolved by the host’s AssetLoader.
| Field | Type | Required | Description |
|---|---|---|---|
src |
string | yes | Asset reference (@name) or literal path. |
circles
Section titled “circles”Filled disks at every feature point (tiny-skia), with per-feature radius, color, opacity, and optional stroke ring. The crisp vector counterpart to MapLibre’s circle layer. Each paint property has an optional *-expr MapLibre-expression sibling evaluated per feature group.

| Field | Type | Required | Description |
|---|---|---|---|
color |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
color-expr |
— | no | A MapLibre color expression (JSON array, e.g. [“match”, [“get”, “c”], “a”, “#f00”, “#0f0”]), evaluated per feature group; overrides the constant color. |
features |
@node |
yes | Reference to another node (@name). |
opacity |
number (0…1) | $param | @node |
no | — |
opacity-expr |
— | no | A MapLibre number expression giving opacity, evaluated per feature group; multiplies both fill and stroke alpha. Overrides the constant opacity. |
radius |
number (0…∞) | $param | @node |
no | — |
radius-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides the constant radius. |
stroke-color |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
stroke-color-expr |
— | no | A MapLibre color expression for the stroke ring, evaluated per feature group; overrides the constant stroke-color. |
stroke-width |
number (0…∞) | $param | @node |
no | — |
stroke-width-expr |
— | no | A MapLibre number expression (px) for the stroke ring, evaluated per feature group; overrides the constant stroke-width. A ring is drawn only when width > 0. |
fill-dabs
Section titled “fill-dabs”Watercolor scatter-dab fill with world-deterministic jitter (seamless across tiles).

| Field | Type | Required | Description |
|---|---|---|---|
color |
color | $param | @node |
yes | sRGB hex color, $param reference, or @node scalar port. |
features |
@node |
yes | Reference to another node (@name). |
hardness |
number (0…1) | $param | @node |
no | — |
opacity |
number (0…1) | $param | @node |
yes | — |
opacity-jitter |
number (0…1) | $param | @node |
no | — |
paint |
number (0…1) | $param | @node |
no | — |
position-jitter |
number (0…1) | $param | @node |
no | — |
radius-px |
number (0…∞) | $param | @node |
yes | — |
size-jitter |
number (0…1) | $param | @node |
no | — |
spacing-px |
number (0…∞) | $param | @node |
yes | — |
value-jitter |
number (0…1) | $param | @node |
no | — |
fill-solid
Section titled “fill-solid”Solid polygon fill with optional outline and Gaussian blur.

| Field | Type | Required | Description |
|---|---|---|---|
blur-sigma |
number (0…∞) | $param | @node |
no | — |
blur-sigma-max |
number (0…∞) | no | Upper bound on blur-sigma for padding, required when blur-sigma is an @node port. Values above it are clamped. |
edge |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
edge-width |
number (0…∞) | $param | @node |
no | — |
features |
@node |
yes | Reference to another node (@name). |
fill |
color | $param | @node |
yes | sRGB hex color, $param reference, or @node scalar port. |
fill-alpha |
number (0…1) | $param | @node |
no | — |
fill-expr |
— | no | A MapLibre color expression (JSON array, e.g. [“match”, [“get”, “class”], “water”, “#88c”, “#ccc”] or [“interpolate”, [“linear”], [“get”, “area”], 0, “#eef”, 1000, “#049”]), evaluated per feature group at paint time. When present it overrides the constant fill; a group whose expression doesn’t resolve to a color is not painted. Unlocks continuous data-driven fills that constant fill can’t express. |
opacity-expr |
— | no | A MapLibre number expression (JSON array) giving fill opacity, evaluated per feature group at paint time. When present it overrides the constant fill-alpha; a group whose expression doesn’t resolve to a number falls back to fill-alpha. |
label-placement
Section titled “label-placement”Place the labels of every text-labels layer against one shared collision index, the way maplibre-gl-js does — so a POI label can knock out an overlapping road name. labels lists the layers bottom-first (paint order, as in stack); priority is top-down, so the last entry places first and wins. Feed the result to each layer’s text-draw node.
| Field | Type | Required | Description |
|---|---|---|---|
labels |
array of @node |
yes | text-labels layers, bottom first. The topmost layer places first. |
Brush stroke along MVT polylines.
| Field | Type | Required | Description |
|---|---|---|---|
brush |
@node |
yes | Reference to another node (@name). |
color |
color | $param | @node |
yes | sRGB hex color, $param reference, or @node scalar port. |
dtime |
number (0…∞) | $param | @node |
no | — |
dtime-stroke-curve |
array of array of number | string | no | Piecewise-linear [[t, y], ...] multiplier on dtime. y scales the per-vertex dtime — y=3 makes the brush linger 3× longer (slower hand), y=0.3 sweeps through 3× faster. Used with dynamics-driven brushes that respond to stroke speed. |
features |
@node |
yes | Reference to another node (@name). |
hardness-stroke-curve |
array of array of number | string | no | Piecewise-linear [[t, y], ...] driving a libmypaint stroke input on the brush. t is normalized stroke progress in [0, 1]; y is an offset added to the setting’s base value. radius is log-space (y=-2.3 ≈ ×0.1, y=+0.69 ≈ ×2); opaque and hardness are linear. |
opacity |
number (0…1) | $param | @node |
no | — |
opacity-stroke-curve |
array of array of number | string | no | Piecewise-linear [[t, y], ...] driving a libmypaint stroke input on the brush. t is normalized stroke progress in [0, 1]; y is an offset added to the setting’s base value. radius is log-space (y=-2.3 ≈ ×0.1, y=+0.69 ≈ ×2); opaque and hardness are linear. |
pressure-base |
number (0…1) | $param | @node |
no | — |
pressure-jitter |
number (0…1) | $param | @node |
no | — |
radius-px |
number (0…∞) | $param | @node |
no | — |
radius-stroke-curve |
array of array of number | string | no | Piecewise-linear [[t, y], ...] driving a libmypaint stroke input on the brush. t is normalized stroke progress in [0, 1]; y is an offset added to the setting’s base value. radius is log-space (y=-2.3 ≈ ×0.1, y=+0.69 ≈ ×2); opaque and hardness are linear. |
line-stamp
Section titled “line-stamp”Repeat a sprite along each polyline, rotated to the line’s tangent (MapLibre line-pattern). Points/polygons ignored. width-px scales the image height to the stroke width; spacing-px sets the advance (0 = the scaled image width, seamless).
| Field | Type | Required | Description |
|---|---|---|---|
features |
@node |
yes | Reference to another node (@name). |
image |
@node |
yes | Reference to another node (@name). |
opacity |
number (0…1) | $param | @node |
no | — |
scale |
number (0…∞) | $param | @node |
no | Extra uniform scale on top of the width fit. Default 1.0. |
spacing-px |
number (0…∞) | $param | @node |
no | Advance between stamps. 0 = the scaled image width (seamless tiling). |
width-px |
number (0…∞) | $param | @node |
no | Stroke width; the image height is fit to it. 0 = native height. |
Stamp a sprite at every input point. Lines and polygons are ignored. Rotation, scale and position jitter are world-deterministic — a given point gets the same jitter no matter which tile renders it, and the three do not correlate. Provide either an image input (one sprite for every point) or, for a data-driven icon-image, a sprite atlas ref plus a name-expr that names each feature’s icon.
| Field | Type | Required | Description |
|---|---|---|---|
features |
@node |
yes | Reference to another node (@name). |
image |
@node |
no | Reference to another node (@name). |
name-expr |
— | no | A MapLibre expression giving each feature’s icon name (MapLibre data-driven icon-image), cropped per group from the sprite atlas. Used instead of an image input; any icon the bound sheet contains is croppable, so no enumeration is needed. |
opacity |
number (0…1) | $param | @node |
no | — |
opacity-expr |
— | no | A MapLibre number expression giving opacity, evaluated per feature group; overrides the constant opacity. |
position-jitter-px |
number (0…∞) | $param | @node |
no | Per-point random offset, ±value canvas pixels, drawn independently on x and y. Breaks up the regular lattice a point-grid leaves. Default 0 (no offset). |
rotation-deg |
number | $param | @node |
no | Constant rotation around each point, in degrees clockwise. |
rotation-deg-expr |
— | no | A MapLibre number expression (degrees clockwise), evaluated per feature group; overrides the constant rotation-deg. |
rotation-jitter-deg |
number (0…∞) | $param | @node |
no | Per-point random rotation, ±value degrees. |
scale |
number (0…∞) | $param | @node |
no | Uniform scale applied to the sprite. Default 1.0 (native size). |
scale-expr |
— | no | A MapLibre number expression, evaluated per feature group; overrides the constant scale. A group whose expression doesn’t resolve to a number falls back to scale. |
scale-jitter |
number (0…∞) | $param | @node |
no | Per-point random scale, ±value as a fraction of scale (0.2 = ±20%). |
sprite |
string | no | Asset reference (@name) or literal path. |
stroke
Section titled “stroke”Crisp constant-width vector stroke along feature polylines (tiny-skia), with cap/join and optional pixel dasharray. The sharp counterpart to line (painterly brush) — for clean cartographic road/boundary lines.

| Field | Type | Required | Description |
|---|---|---|---|
cap |
butt | round | square |
no | — |
color |
color | $param | @node |
yes | sRGB hex color, $param reference, or @node scalar port. |
color-expr |
— | no | A MapLibre color expression (JSON array, e.g. [“match”, [“get”, “class”], “river”, “#48b”, “#888”]), evaluated per feature group at paint time. When present it overrides the constant color; a group whose expression doesn’t resolve to a color falls back to color. Unlocks data-driven stroke colors. |
dasharray |
array of number (0…∞) | string | no | On/off lengths in pixels; omit for solid. Each length may be a $param. |
features |
@node |
yes | Reference to another node (@name). |
gap-width-expr |
— | no | A MapLibre number expression (JSON array) giving the casing gap in pixels, evaluated per feature group at paint time. When present it overrides the constant gap-width-px; a group whose expression doesn’t resolve to a number falls back to gap-width-px. |
gap-width-px |
number | no | MapLibre line-gap-width: when > 0 the stroke becomes a casing — two parallel bands of width-px each, their inner edges this many pixels apart (outer footprint gap + 2 * width, centred on the line). 0 strokes the centreline. |
join |
miter | round | bevel |
no | — |
opacity |
number (0…1) | $param | @node |
no | — |
opacity-expr |
— | no | A MapLibre number expression (JSON array) giving stroke opacity, evaluated per feature group at paint time. When present it overrides the constant opacity; a group whose expression doesn’t resolve to a number falls back to opacity. |
width-expr |
— | no | A MapLibre number expression (JSON array, e.g. [“interpolate”, [“linear”], [“zoom”], 10, 1, 16, 4]) giving stroke width in pixels, evaluated per feature group at paint time. When present it overrides the constant width-px; a group whose expression doesn’t resolve to a number falls back to width-px. |
width-px |
number (0…∞) | $param | @node |
no | — |
Text labels (MapLibre symbol-placement): placement: point (default) labels each feature point, line / line-center walk each polyline with tangent-rotated glyphs. font is an ordered fallback stack of font and/or glyphs source names; text is a literal string or a MapLibre string expression evaluated per feature group. Paint properties have optional *-expr siblings; layout knobs are build-time constants in em. Collision is on by default and is deterministic across tiles: candidates come from this tile plus the 8 neighbour tiles (host-bound under <source>.<layer>@dx,dy), so borders stay seamless. Set source/layer (the upstream feature source) to enable neighbour gathering; without them collision is centre-tile-only. icon-name / icon-name-expr add MapLibre’s icon-image half: the icon is placed together with the text against the same index, so a symbol shows both or neither unless icon-optional / text-optional say otherwise. font and text are required unless the symbol is icon-only.
| Field | Type | Required | Description |
|---|---|---|---|
allow-overlap |
boolean | no | MapLibre text-allow-overlap: place the label even if it collides. It still reserves its box (blocking later labels) unless ignore-placement. Default false. |
anchor |
center | left | right | top | bottom | top-left | top-right | bottom-left | bottom-right |
no | Which part of the label block sits on the point (point placement). Default center. |
anchor-variants |
array of center | left | right | top | bottom | top-left | top-right | bottom-left | bottom-right |
no | MapLibre text-variable-anchor: anchors tried in order on collision, the first free one placed (point placement). Overrides anchor when set. |
collide |
boolean | no | Whether to run deterministic label collision. Default true (MapLibre’s default). Set false to draw every label (the pre-collision behaviour). |
color |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
color-expr |
— | no | A MapLibre color expression, evaluated per feature group; overrides the constant color. |
features |
@node |
yes | Reference to another node (@name). |
filter-expr |
— | no | The upstream features filter, reproduced when gathering neighbour candidates so they are filtered identically to this tile’s own features. Set it to whatever the features node uses. |
font |
array of string | no | Ordered fallback stack of font and/or glyphs source names from the document’s sources. Outline fonts and SDF glyph stacks mix freely; the first entry covering a char shapes it. Also the default/fallback stack for font-expr and unlisted font-stacks keys. |
font-expr |
— | no | A MapLibre expression yielding an array of font names, evaluated per feature group (MapLibre data-driven text-font); overrides the constant font. Each result is canonicalized (names joined with ,) and looked up in font-stacks; an unlisted stack, a non-array result, or an eval error falls back to font. Every stack a host may need must be enumerable in font-stacks (wasm hosts pre-bind glyph assets). |
font-stacks |
object | no | Named dynamic font stacks: canonical stack key (font names joined with ,) → ordered font/glyphs source names. Consulted by font-expr and by format text sections carrying text-font. Declaration order fixes each stack’s stable id (used by the layout cache and cross-tile collision). |
halo-color |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
halo-color-expr |
— | no | A MapLibre color expression for the halo, evaluated per feature group; overrides the constant halo-color. |
halo-width |
number (0…∞) | $param | @node |
no | Halo radius in px around each glyph. Default 0 (no halo). |
halo-width-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides the constant halo-width. |
icon-allow-overlap |
boolean | no | MapLibre icon-allow-overlap. A symbol carries one overlap decision, so with text present this and allow-overlap must both be set for the symbol to ignore collision. Default false. |
icon-anchor |
center | left | right | top | bottom | top-left | top-right | bottom-left | bottom-right |
no | Which part of the icon sits on the point (MapLibre icon-anchor). Default center. |
icon-ignore-placement |
boolean | no | MapLibre icon-ignore-placement; with text present it pairs with ignore-placement the same way as the overlap flags. Default false. |
icon-name |
string | no | Constant MapLibre icon-image: the sprite to draw at each point, cropped from icon-sprite. Needs icon-sprite. |
icon-name-expr |
— | no | A MapLibre expression naming each feature’s icon (data-driven icon-image), cropped from icon-sprite; overrides icon-name. A group resolving to an empty/unknown name draws no icon and places as a text-only symbol. |
icon-offset |
array of number | no | MapLibre icon-offset: shift [x, y] in px, itself scaled by icon-size. Default [0, 0]. |
icon-opacity |
number (0…1) | $param | @node |
no | — |
icon-opacity-expr |
— | no | A MapLibre number expression giving the icon’s opacity; overrides icon-opacity. |
icon-optional |
boolean | no | MapLibre icon-optional: let the text place when the icon’s box is blocked. Default false — icon and text place as one unit. |
icon-padding-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides icon-padding-px. |
icon-padding-px |
number (0…∞) | no | MapLibre icon-padding: collision-box inflation around the icon, in px. Default 2. |
icon-rotate-deg |
number | no | MapLibre icon-rotate: rotation in degrees clockwise about the icon centre. Default 0. |
icon-rotate-deg-expr |
— | no | A MapLibre number expression (degrees clockwise); overrides icon-rotate-deg. |
icon-size |
number (0…∞) | no | MapLibre icon-size: multiplier on the sprite’s authored display size (atlas pixels over its pixel ratio). Default 1. |
icon-size-expr |
— | no | A MapLibre number expression, evaluated per feature group; overrides icon-size. |
icon-sprite |
string | no | Asset reference (@name) or literal path. |
icon-text-fit |
none | width | height | both |
no | MapLibre icon-text-fit: stretch the icon to the box its label occupies, on the named axes. The sprite’s stretchX/stretchY/content metadata decides which bands absorb the growth, so a shield keeps its corners; a sprite without it scales whole. The fitted box is also the icon’s collision box. Default none. |
icon-text-fit-padding |
array of number | no | MapLibre icon-text-fit-padding: [top, right, bottom, left] px added around the label’s box before the icon is fitted to it. Default [0, 0, 0, 0]. |
ignore-placement |
boolean | no | MapLibre text-ignore-placement: don’t let this label block later ones (skip inserting its collision box). Default false. |
justify |
auto | left | center | right |
no | Line alignment within the wrapped block. Default auto (follows the anchor’s horizontal side). |
keep-upright |
boolean | no | Flip a right-to-left label so it reads upright (MapLibre text-keep-upright). Line placement only. Default true. |
layer |
string | no | Upstream feature layer name (with source). Used only to name neighbour bindings for cross-tile collision. |
letter-spacing-em |
number | no | Extra advance per glyph in em. Default 0. |
line-height |
number | no | Baseline-to-baseline distance in em. Default 1.2. |
max-angle-deg |
number (0…∞) | no | Max cumulative bend in degrees the line may turn over a label-length window before the anchor is rejected (MapLibre text-max-angle). Line placement only. Default 45. |
max-extent-px |
number (0…∞) | no | Canvas pad this node requests; labels whose bbox half-extent exceeds it are culled with a warning. Default 128. |
max-width-em |
number (0…∞) | no | Wrap target width in em. Default 10; 0 disables wrapping. |
max-zoom |
integer (0…24) | no | Style layer zoom gate: draw nothing above this zoom (mirrors the features node). |
min-zoom |
integer (0…24) | no | Style layer zoom gate: draw nothing below this zoom (mirrors the features node). |
min-zoom-field |
string | no | Per-feature min_zoom property name, reproduced for neighbour candidate filtering (mirrors the features node). |
offset-em |
array of number | no | Block shift [x, y] in em, applied after anchoring. Default [0, 0]. |
opacity |
number (0…1) | $param | @node |
no | — |
opacity-expr |
— | no | A MapLibre number expression giving opacity, evaluated per feature group; multiplies both fill and halo alpha. Overrides the constant opacity. |
outline-sdf |
boolean | no | Render outline-font glyphs through the SDF field-sampling path (maplibre-gl-js style, which draws every glyph from an SDF) instead of a per-glyph vector fill / stroke. The halo then comes from a distance threshold rather than a stroke, matching MapLibre’s halo shape and cost. SDF glyph (glyphs) stacks are unaffected. Default true. |
padding-expr |
— | no | A MapLibre number expression (MapLibre text-padding), evaluated per feature group; overrides the constant padding-px for that group’s collision boxes. |
padding-px |
number (0…∞) | no | Collision-box inflation in px on every side. Default 2. |
placement |
point | line | line-center |
no | MapLibre symbol-placement. point (default) labels each feature point. line repeats labels along each polyline every spacing-px; line-center places one at each line’s arc-length midpoint. Line placement ignores wrapping (max-width-em) and lays out a single line along the path. |
radial-offset |
number | no | MapLibre text-radial-offset: em distance each anchor-variants entry pushes the block away from the point in its direction. Default 0. |
size |
number (0…∞) | $param | @node |
no | Font size in px. Default 16. |
size-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides the constant size. |
sort-key-expr |
— | no | A MapLibre number expression (MapLibre symbol-sort-key), evaluated per feature group; lower values place first under collision. Absent = 0. |
source |
string | no | Upstream feature source name (matches the features node). Used only to name the neighbour tile bindings for cross-tile collision. Omit to collide within this tile only. |
spacing-px |
number (1…∞) | no | Gap in px between successive line anchors (MapLibre symbol-spacing). Line placement only. Default 250. |
text |
— | no | The label: a literal string, or a MapLibre string expression (evaluated per feature group; empty/failed → the group draws nothing). |
text-optional |
boolean | no | MapLibre text-optional: let the icon place when the text’s box is blocked. Default false. |
transform |
none | uppercase | lowercase |
no | Case transform applied before shaping. Default none. |
text-draw
Section titled “text-draw”Draw one label layer’s placed labels: labels is the layer’s text-labels node, placement the shared label-placement node that decided it (wire the same text-labels node into both). Styling and layout live on text-labels; this node only rasterizes the winners.
| Field | Type | Required | Description |
|---|---|---|---|
labels |
@node |
yes | Reference to another node (@name). |
max-extent-px |
number (0…∞) | no | Canvas pad (px) this layer’s labels need to cross a tile border un-clipped. Mirrors the text-labels field of the same name. |
placement |
@node |
yes | Reference to another node (@name). |
text-labels
Section titled “text-labels”Text labels (MapLibre symbol-placement): placement: point (default) labels each feature point, line / line-center walk each polyline with tangent-rotated glyphs. font is an ordered fallback stack of font and/or glyphs source names; text is a literal string or a MapLibre string expression evaluated per feature group. Paint properties have optional *-expr siblings; layout knobs are build-time constants in em. Collision is on by default and is deterministic across tiles: candidates come from this tile plus the 8 neighbour tiles (host-bound under <source>.<layer>@dx,dy), so borders stay seamless. Set source/layer (the upstream feature source) to enable neighbour gathering; without them collision is centre-tile-only. icon-name / icon-name-expr add MapLibre’s icon-image half: the icon is placed together with the text against the same index, so a symbol shows both or neither unless icon-optional / text-optional say otherwise. font and text are required unless the symbol is icon-only. Emits placement candidates instead of pixels: wire this node into a label-placement node and draw the result with text-draw.
| Field | Type | Required | Description |
|---|---|---|---|
allow-overlap |
boolean | no | MapLibre text-allow-overlap: place the label even if it collides. It still reserves its box (blocking later labels) unless ignore-placement. Default false. |
anchor |
center | left | right | top | bottom | top-left | top-right | bottom-left | bottom-right |
no | Which part of the label block sits on the point (point placement). Default center. |
anchor-variants |
array of center | left | right | top | bottom | top-left | top-right | bottom-left | bottom-right |
no | MapLibre text-variable-anchor: anchors tried in order on collision, the first free one placed (point placement). Overrides anchor when set. |
collide |
boolean | no | Whether to run deterministic label collision. Default true (MapLibre’s default). Set false to draw every label (the pre-collision behaviour). |
color |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
color-expr |
— | no | A MapLibre color expression, evaluated per feature group; overrides the constant color. |
features |
@node |
yes | Reference to another node (@name). |
filter-expr |
— | no | The upstream features filter, reproduced when gathering neighbour candidates so they are filtered identically to this tile’s own features. Set it to whatever the features node uses. |
font |
array of string | no | Ordered fallback stack of font and/or glyphs source names from the document’s sources. Outline fonts and SDF glyph stacks mix freely; the first entry covering a char shapes it. Also the default/fallback stack for font-expr and unlisted font-stacks keys. |
font-expr |
— | no | A MapLibre expression yielding an array of font names, evaluated per feature group (MapLibre data-driven text-font); overrides the constant font. Each result is canonicalized (names joined with ,) and looked up in font-stacks; an unlisted stack, a non-array result, or an eval error falls back to font. Every stack a host may need must be enumerable in font-stacks (wasm hosts pre-bind glyph assets). |
font-stacks |
object | no | Named dynamic font stacks: canonical stack key (font names joined with ,) → ordered font/glyphs source names. Consulted by font-expr and by format text sections carrying text-font. Declaration order fixes each stack’s stable id (used by the layout cache and cross-tile collision). |
halo-color |
color | $param | @node |
no | sRGB hex color, $param reference, or @node scalar port. |
halo-color-expr |
— | no | A MapLibre color expression for the halo, evaluated per feature group; overrides the constant halo-color. |
halo-width |
number (0…∞) | $param | @node |
no | Halo radius in px around each glyph. Default 0 (no halo). |
halo-width-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides the constant halo-width. |
icon-allow-overlap |
boolean | no | MapLibre icon-allow-overlap. A symbol carries one overlap decision, so with text present this and allow-overlap must both be set for the symbol to ignore collision. Default false. |
icon-anchor |
center | left | right | top | bottom | top-left | top-right | bottom-left | bottom-right |
no | Which part of the icon sits on the point (MapLibre icon-anchor). Default center. |
icon-ignore-placement |
boolean | no | MapLibre icon-ignore-placement; with text present it pairs with ignore-placement the same way as the overlap flags. Default false. |
icon-name |
string | no | Constant MapLibre icon-image: the sprite to draw at each point, cropped from icon-sprite. Needs icon-sprite. |
icon-name-expr |
— | no | A MapLibre expression naming each feature’s icon (data-driven icon-image), cropped from icon-sprite; overrides icon-name. A group resolving to an empty/unknown name draws no icon and places as a text-only symbol. |
icon-offset |
array of number | no | MapLibre icon-offset: shift [x, y] in px, itself scaled by icon-size. Default [0, 0]. |
icon-opacity |
number (0…1) | $param | @node |
no | — |
icon-opacity-expr |
— | no | A MapLibre number expression giving the icon’s opacity; overrides icon-opacity. |
icon-optional |
boolean | no | MapLibre icon-optional: let the text place when the icon’s box is blocked. Default false — icon and text place as one unit. |
icon-padding-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides icon-padding-px. |
icon-padding-px |
number (0…∞) | no | MapLibre icon-padding: collision-box inflation around the icon, in px. Default 2. |
icon-rotate-deg |
number | no | MapLibre icon-rotate: rotation in degrees clockwise about the icon centre. Default 0. |
icon-rotate-deg-expr |
— | no | A MapLibre number expression (degrees clockwise); overrides icon-rotate-deg. |
icon-size |
number (0…∞) | no | MapLibre icon-size: multiplier on the sprite’s authored display size (atlas pixels over its pixel ratio). Default 1. |
icon-size-expr |
— | no | A MapLibre number expression, evaluated per feature group; overrides icon-size. |
icon-sprite |
string | no | Asset reference (@name) or literal path. |
icon-text-fit |
none | width | height | both |
no | MapLibre icon-text-fit: stretch the icon to the box its label occupies, on the named axes. The sprite’s stretchX/stretchY/content metadata decides which bands absorb the growth, so a shield keeps its corners; a sprite without it scales whole. The fitted box is also the icon’s collision box. Default none. |
icon-text-fit-padding |
array of number | no | MapLibre icon-text-fit-padding: [top, right, bottom, left] px added around the label’s box before the icon is fitted to it. Default [0, 0, 0, 0]. |
ignore-placement |
boolean | no | MapLibre text-ignore-placement: don’t let this label block later ones (skip inserting its collision box). Default false. |
justify |
auto | left | center | right |
no | Line alignment within the wrapped block. Default auto (follows the anchor’s horizontal side). |
keep-upright |
boolean | no | Flip a right-to-left label so it reads upright (MapLibre text-keep-upright). Line placement only. Default true. |
layer |
string | no | Upstream feature layer name (with source). Used only to name neighbour bindings for cross-tile collision. |
letter-spacing-em |
number | no | Extra advance per glyph in em. Default 0. |
line-height |
number | no | Baseline-to-baseline distance in em. Default 1.2. |
max-angle-deg |
number (0…∞) | no | Max cumulative bend in degrees the line may turn over a label-length window before the anchor is rejected (MapLibre text-max-angle). Line placement only. Default 45. |
max-extent-px |
number (0…∞) | no | Canvas pad this node requests; labels whose bbox half-extent exceeds it are culled with a warning. Default 128. |
max-width-em |
number (0…∞) | no | Wrap target width in em. Default 10; 0 disables wrapping. |
max-zoom |
integer (0…24) | no | Style layer zoom gate: draw nothing above this zoom (mirrors the features node). |
min-zoom |
integer (0…24) | no | Style layer zoom gate: draw nothing below this zoom (mirrors the features node). |
min-zoom-field |
string | no | Per-feature min_zoom property name, reproduced for neighbour candidate filtering (mirrors the features node). |
offset-em |
array of number | no | Block shift [x, y] in em, applied after anchoring. Default [0, 0]. |
opacity |
number (0…1) | $param | @node |
no | — |
opacity-expr |
— | no | A MapLibre number expression giving opacity, evaluated per feature group; multiplies both fill and halo alpha. Overrides the constant opacity. |
outline-sdf |
boolean | no | Render outline-font glyphs through the SDF field-sampling path (maplibre-gl-js style, which draws every glyph from an SDF) instead of a per-glyph vector fill / stroke. The halo then comes from a distance threshold rather than a stroke, matching MapLibre’s halo shape and cost. SDF glyph (glyphs) stacks are unaffected. Default true. |
padding-expr |
— | no | A MapLibre number expression (MapLibre text-padding), evaluated per feature group; overrides the constant padding-px for that group’s collision boxes. |
padding-px |
number (0…∞) | no | Collision-box inflation in px on every side. Default 2. |
placement |
point | line | line-center |
no | MapLibre symbol-placement. point (default) labels each feature point. line repeats labels along each polyline every spacing-px; line-center places one at each line’s arc-length midpoint. Line placement ignores wrapping (max-width-em) and lays out a single line along the path. |
radial-offset |
number | no | MapLibre text-radial-offset: em distance each anchor-variants entry pushes the block away from the point in its direction. Default 0. |
size |
number (0…∞) | $param | @node |
no | Font size in px. Default 16. |
size-expr |
— | no | A MapLibre number expression (px), evaluated per feature group; overrides the constant size. |
sort-key-expr |
— | no | A MapLibre number expression (MapLibre symbol-sort-key), evaluated per feature group; lower values place first under collision. Absent = 0. |
source |
string | no | Upstream feature source name (matches the features node). Used only to name the neighbour tile bindings for cross-tile collision. Omit to collide within this tile only. |
spacing-px |
number (1…∞) | no | Gap in px between successive line anchors (MapLibre symbol-spacing). Line placement only. Default 250. |
text |
— | no | The label: a literal string, or a MapLibre string expression (evaluated per feature group; empty/failed → the group draws nothing). |
text-optional |
boolean | no | MapLibre text-optional: let the icon place when the text’s box is blocked. Default false. |
transform |
none | uppercase | lowercase |
no | Case transform applied before shaping. Default none. |
Map renders on this site are made fromOpenStreetMap data viaProtomaps (© OpenStreetMap contributors), elevation from Re:Earth Terrain,Mapterhorn andEGM2008 (NGA), and aerial imagery from GSI Japan(© 国土地理院). The painterly styles use CC0 brushes byDavid Revoy.