Language
Function reference.
Every builtin the evaluator knows about. Use any of these inside a
utility binding (utility-[expr]),
a layer filter (filter:), a
block property (extrude:,
geometry:), or as a match-arm
value.
Inputs are coerced — strings get parseFloat'd,
booleans become 0/1, anything else becomes 0. Numeric ops follow JS
semantics except division-by-zero returns 0 (no Infinity).
Math
Number-in / number-out helpers. Inputs are coerced via `toNumber` (strings parseFloat, booleans 0/1, anything else 0). Division-by-zero in the language operators returns 0 silently — these helpers follow the same convention.
clamp
clamp(value, min, max)
Pin value into the closed range [min, max]. Equivalent to min(max(value, min), max) but a single call.
size-[clamp(.speed / 50, 4, 24)]min
min(a, b, …)
Smallest of all arguments. Variadic — pass any number of values.
stroke-[min(.width, 8)]opacity-[min(.alpha, 0.7)]max
max(a, b, …)
Largest of all arguments. Variadic.
stroke-[max(.width, 1)]round
round(value)
Round half-up to the nearest integer.
size-[round(.zoom)]floor
floor(value)
Round down to the next integer.
size-[floor(.density / 100)]ceil
ceil(value)
Round up to the next integer.
size-[ceil(.depth)]abs
abs(value)
Absolute value.
stroke-[abs(.delta)]sqrt
sqrt(value)
Square root. Negative inputs return NaN; the toNumber pipeline coerces NaN to 0 in arithmetic.
size-[sqrt(.area)]pow
pow(base, exponent)
Raise base to exponent. pow(x, 0.5) is equivalent to sqrt(x).
size-[pow(.population, 0.3)]exp
exp(value)
Natural exponential — e ^ value.
size-[exp(.score / 1000)]log
log(value)
Natural log — ln(value). Inputs ≤ 0 are clamped to 1e-10 to avoid -Infinity.
size-[log(.population)]ln
ln(value)
Alias for log — kept so converted Mapbox styles using ["ln", x] round-trip 1:1.
log10
log10(value)
Base-10 log. Same negative-input clamp as log.
fill-[interpolate(log10(.population), 3, white-100, 7, red-500)]log2
log2(value)
Base-2 log. Same clamp as log.
size-[log2(.zoom)]scale
scale(value, factor)
Multiply value by factor. Pure sugar over * for chained pipe operations: .x | scale(2).
size-[.height | scale(0.5)]Trigonometry
Standard trig in **radians**. Convert from degrees with `value * PI / 180` or use the `TAU` constant for full-revolution math.
sin
sin(radians)
Sine.
stroke-[sin(.angle) * 5]cos
cos(radians)
Cosine.
size-[cos(.heading) * 10]tan
tan(radians)
Tangent.
asin
asin(value)
Inverse sine. Inputs outside [-1, 1] return NaN.
acos
acos(value)
Inverse cosine. Inputs outside [-1, 1] return NaN.
atan
atan(value)
Inverse tangent.
atan2
atan2(y, x)
Two-arg arctangent — angle of the vector (x, y) in [-π, π]. Use this for "rotate to face direction" since it handles all four quadrants.
size-[atan2(.dy, .dx)]Stops & gates
Builtins that pick or blend between values. Both work for any input — `zoom` (camera state), `.field` (feature property), arithmetic results.
interpolate
interpolate(input, x1, y1, x2, y2, …)
Linear interpolation between (xi, yi) stops. When input is below x1 returns y1; above the last xN returns yN; in between blends linearly. Numeric values blend; non-numeric (e.g. color hex) snap to the nearest stop without blending. The single most-used builtin — covers every Mapbox interpolate zoom-driven paint property.
opacity-[interpolate(zoom, 8, 40, 14, 100)]stroke-[interpolate(zoom, 11, 1, 19, 2.5)]fill-[interpolate(.population, 0, white-100, 1e6, red-500)]step
step(input, default, stop1, val1, stop2, val2, …) // OR step(value, threshold, below, above)
Discrete-stop gate. Two shapes: the **N-stop** form (Mapbox-spec — preferred) returns default while input < stop1, then walks stops left-to-right and returns the val for the largest stop_i ≤ input. The legacy **2-stop** form (4 args) is below when value < threshold, else above. Distinguish by arg count: even = legacy, odd ≥ 5 = N-stop.
size-[step(.rank, 0.5, 5, 0.7, 10, 1)] // N-stop: default 0.5, jumps at rank 5 → 0.7, rank 10 → 1opacity-[step(zoom, 10, 30, 100)] // legacy: < 10 → 30, else 100interpolate_exp
interpolate_exp(input, base, x1, y1, x2, y2, …)
Exponential-curve interpolation — Mapbox ["interpolate", ["exponential", base], …]. Same stop shape as interpolate but with a leading base that shapes the between-stops curve; base = 1 is mathematically linear (identical to interpolate).
size-[interpolate_exp(zoom, 1.5, 8, 2, 16, 20)]interpolate_lab
interpolate_lab(input, x1, color1, x2, color2, …)
Colour interpolation in CIELAB space — Mapbox ["interpolate-lab", …]. Stop values resolve to colours at eval time; blends perceptually (smoother than RGB lerp). Stop xi must be literal numbers. Curve is linear only.
fill-[interpolate_lab(.t, 0, blue-500, 1, red-500)]interpolate_hcl
interpolate_hcl(input, x1, color1, x2, color2, …)
Colour interpolation in HCL (LCh) space — Mapbox ["interpolate-hcl", …]. Like interpolate_lab but interpolates hue on the shortest arc, keeping chroma vivid through the blend.
fill-[interpolate_hcl(.t, 0, yellow-400, 1, purple-600)]Strings
String-coercing helpers. Numeric inputs stringify via `String()`; null / undefined drop. The label resolver runs strings through these the same way it does for inline `{template}` syntax.
concat
concat(a, b, c, …)
Concatenate any number of arguments after coercing each to its string form. Null / undefined are skipped (matches the Mapbox spec). Common shape inside label-[ for compound labels — bilingual names, prefix-suffix wraps, units suffixed to numbers.
label-[concat(.name, " (", .country, ")")]label-[concat(round(.elevation_m), " m")]downcase
downcase(value)
Lowercase the string form of value. Coerces non-strings via String().
label-[downcase(.name)]upcase
upcase(value)
Uppercase the string form of value. Same coercion.
label-[upcase(.country_code)]String / type ops
String slicing, search, number formatting, and the Mapbox type-cast family. These round-trip the corresponding Mapbox expressions 1:1 — a converted style that calls them keeps working even though the converter usually rewrites the casts into a coalesce chain.
typeof
typeof(value)
Mapbox ["typeof", value]. Returns "string", "number", "boolean", "object", or "null". Useful inside a filter: to branch on a property's shape.
filter: typeof(.name) == "string"slice
slice(input, start, end?)
Substring (string input) or sub-array (array input) — Mapbox ["slice", …]. Negative indices count from the end. Non-string / non-array input returns null.
label-[slice(.iso_code, 0, 2)]index_of
index_of(needle, haystack, from?)
First index of needle in a string or array (Mapbox ["index-of", …]; the hyphen form index-of also routes here). Returns -1 when not found.
size-[index_of("toll", .tags) >= 0]number_format
number_format(input, minFrac?, maxFrac?, locale?, currency?)
Locale-aware number formatting via Intl.NumberFormat — Mapbox ["number-format", …]. Positional args (the form the converter emits) or an options-object second arg both work; null slots take spec defaults.
label-[number_format(.population, 0, 0, "en-US")]to_number
to_number(value, …fallbacks)
Mapbox ["to-number", …] (alias number). Returns the first arg that converts to a finite number — strings via Number(), booleans as 0/1 — else null. Use it to harden a string property before arithmetic.
size-[to_number(.height_str)]to_string
to_string(value)
Mapbox ["to-string", value] (alias string). Coerces to a string — numbers via String(), booleans to "true" / "false", objects via JSON.stringify, null/undefined to "".
label-[to_string(.rank)]to_boolean
to_boolean(value)
Mapbox ["to-boolean", value] (alias boolean). Spec false-y values (0, "", null, undefined, NaN) become false; everything else true.
filter: to_boolean(.is_capital)to_color
to_color(value, …fallbacks)
Mapbox ["to-color", …]. Returns the first arg that parses as a hex colour (#rgb / #rgba / #rrggbb / #rrggbbaa), else null. Non-string args skip to the next fallback.
fill-[to_color(.color_hex, gray-400)]Constants
Compile-time constants. No-arg builtins.
PI
PI
π ≈ 3.14159. Half a revolution.
stroke-[sin(.heading * PI / 180) * 5]TAU
TAU
2π ≈ 6.28318. Full revolution. Often nicer than 2 * PI.
pi
pi()
π as a zero-arg builtin call — same value as PI. Kept for 1:1 round-trip with Mapbox ["pi"].
e
e()
Euler's number — ≈ 2.71828. Mapbox ["e"] round-trip.
ln2
ln2()
ln(2) ≈ 0.69315. Mapbox ["ln2"] round-trip.
Array
Helpers for array values. The match-arm value path and geometry generators (`polygon`, `linestring`) produce arrays.
length
length(array)
Number of elements. Returns 0 for non-arrays.
size-[length(.tags)][i] index
array[i]
Zero-based subscript. Out-of-bounds returns null. Bracket form, not a function — read in the parser.
fill-[.colors[0]]Geometry generators
Construct coordinate arrays / GeoJSON-shaped values from numbers. Used inside `geometry: <expr>` block-property to build a per-feature mesh from properties (e.g. draw a circle around each city sized by population).
circle
circle(cx, cy, radius, segments?)
Polygon ring approximating a circle. segments defaults to 32 (clamped ≥ 4). Returns a closed array of [lon, lat] pairs.
geometry: circle(.lon, .lat, .radius, 64)arc
arc(cx, cy, radius, startRad, endRad, segments?)
Open polyline along an arc from startRad to endRad, both in radians. segments defaults to 32 (clamped ≥ 2).
geometry: arc(.cx, .cy, 5, 0, PI, 24)polygon
polygon(points)
Wrap a [[lon, lat], …] ring as a GeoJSON Polygon. Caller must close the ring (or use circle which closes for you).
geometry: polygon(.boundary)linestring
linestring(points)
Wrap a [[lon, lat], …] array as a GeoJSON LineString.
geometry: linestring(.path)Runtime accessors
Names + accessor builtins the evaluator resolves against live camera / feature state (not the plain `callBuiltin` args). The bare identifiers (`zoom`, `pitch`, `.field`) and the `get` / `properties` accessor calls all read the live props bag.
zoom
zoom
Current camera zoom level (float). Sampled per-frame. Inject in any expression — most commonly inside interpolate(zoom, …).
opacity-[interpolate(zoom, 8, 40, 14, 100)]pitch
pitch
Current camera pitch in degrees — Mapbox ["pitch"]. Sampled per-frame on the render path; null at decode time. Bare name, like zoom.
opacity-[interpolate(pitch, 0, 100, 60, 30)].field
.field_name
Feature property accessor. .height reads the height property from the current feature's tags. Returns null when the property is missing — pair with ?? for a fallback.
fill-extrusion-height-[.height ?? 5]filter: .class == "highway"get
get("key")
Feature property accessor for keys the bare-dot form can't name — Mapbox ["get", key]. Use it for colon-bearing locale keys (name:ko, name:latin) or a dynamic key (get(.field_name)). Returns null when absent.
label-[get("name:ko") ?? get("name")]properties
properties()
The whole feature-properties object — Mapbox ["properties"]. Strips the reserved $-sigil camera/meta keys the runtime injects, returning only the feature's own properties.
filter: typeof(properties()) == "object"Problem on this page?