Map styling
The Styling Foundations Module holds what every part of the map shares as semantic knobs. They cover label, icon and road sizes, the label typeface, the ten map colours and the accent, and a globe with a sky.
- Each knob reaches across the whole style.
labels.sizeFactorresizes every label, POIs and road shields included, andcolors.roadMajorrecolours every shade of the major roads. The other style-owned modules each hold the look of one part. - The knobs are semantic, not layer ids. Like every module’s settings, they are listed as data in a knob catalogue, and
setKnobchecks each value against it. MapLibre layers you edit by hand, throughstyling.layersormap.mapLibreMap, have no catalogue and depend on the layer ids of one style version.
The playground below builds one control per knob from the catalogues of this module and the other style-owned ones.
Each feature built on the knobs has its own guide:
| Guide | Covers |
|---|---|
| Map colours and the accent | setMapColors over the ten map colours, and the accent the modules’ own drawing defaults to |
| Map typeface | The labels.typeface knob, and your own font files for every label on the map |
| Globe and sky | The view knobs: globe projection, sky, horizon and the colour behind the map |
| Borrowed looks | The parts of places, routes and fetched incidents that follow the style’s own looks |
| Editing style layers | styling.layers, for what no knob covers |
Initialization
import { TomTomMap, StylingFoundationsModule } from '@tomtom-org/maps-sdk/map';
const map = new TomTomMap({ mapLibre: { container: 'map' } });const styling = await StylingFoundationsModule.get(map);Pass settings to apply them right away. The configuration nests each setting along its knob id, so labels.sizeFactor is labels: { sizeFactor }:
const styling = await StylingFoundationsModule.get(map, { labels: { sizeFactor: 1.2 }, colors: { water: '#0fa8c8' } });- A map has one module. A second
get()returns the same instance and merges the settings you pass to it over what it holds, one level deep, asupdateConfigdoes. - The map is themed from the first frame.
getresolves once the style has loaded, before the map draws it. Knobs you pass togetor set right after it land on that frame instead of fading in from the style’s own look (Themed map).
Knobs
Every adjustable thing is a knob with a stable id, the setting’s path in the configuration. Set one with setKnob, several at once with setKnobs, read one with getKnob, and restore the style’s own value with resetKnob, as on every module:
import { getKnob, resetKnob, setKnob, setKnobs, stylingFoundationsKnobCatalogue } from '@tomtom-org/maps-sdk/map';
const knobs = stylingFoundationsKnobCatalogue;setKnob(styling, knobs, 'labels.sizeFactor', 1.3); // every base-map label 30% biggersetKnob(styling, knobs, 'roads.widthFactor', 0.8); // thinner roads, hierarchy keptsetKnobs(styling, knobs, { 'colors.roadMajor': '#f59e0b', 'view.projection': 'globe' }); // one restyle
getKnob(styling, knobs, 'roads.widthFactor'); // 0.8resetKnob(styling, knobs, 'roads.widthFactor'); // back to the style's widthstyling.resetConfig(); // everything back to the style as shippedUse the knob functions for values held as data, from a control, storage or a language model, since they check each value against the catalogue. Use applyConfig and updateConfig for settings your code writes, typed. They don’t check values at run time, and updateConfig({ colors: { water } }) replaces every colour you set before. Changing a setting compares the two.
How knobs work
- Most knobs write the loaded style’s layers. The
viewknobs write the map itself.colors.accentwrites nothing, and the modules that draw their own layers read it. - One engine per map applies the knobs, and the look knobs of the POIs, traffic and terrain modules restyle the same loaded style through it. Knobs on one layer property compose, whichever module set them. For example,
labels.sizeFactorhere andsizeFactoronPOIsModulemultiply on the POI labels. All of them land again after a style switch. - A knob writes the whole value of each property it reaches, worked out from the style’s own value. If you set one of those properties yourself with
map.mapLibreMap.setPaintProperty, even to an expression that readsfeature-state, the knob replaces your value whenever it applies. That happens when you set or reset it, and after a style switch. - No knob shows or hides a layer group (water, 3D buildings, road shields). The Base Map Module does that.
| Kind | Takes | What it does |
|---|---|---|
| factor | a multiplier, 1 = as the style ships | multiplies the style’s own value, so zoom ramps and the road hierarchy are kept. A zoom ramp has each stop’s output scaled, and any other expression E becomes ["*", 1.3, E] |
| number | a value in the knob’s range and units | sets that part of the map’s view, such as view.light.direction in degrees |
| colour | any CSS colour | replaces the colour and re-derives the shades the style built from it. Recolouring the major roads recolours their darker outline by the same offset. colors.accent paints no layer, and the modules read it |
| toggle | true / false | view.sky.visible turns the sky on or off |
| enum | one of the knob’s options | picks a mode, such as the projection |
Every knob also follows the same rules:
- A value outside its range or of the wrong kind throws a
RangeErrornaming the knob and what it takes. An unknown id throws anError. A failed call changes nothing. getKnobreads the value in force, which is the one you set or the loaded style’s own. It returnsundefinedwhere the style computes the value from the data, andresetKnobstill restores it.- The SDK re-applies the knobs after every
setStyle, and a clean switch drops them (Style changes). getConfig()returns the knobs you set as plain data, ready to store and re-apply (Settings).- The ten map colours follow the TomTom styles’ taxonomy, re-verified on every style release. Every other knob needs no knowledge of the style (How durable is this?).
- Knobs reach only the style’s layers and the map’s view. What the SDK draws itself (routes, places, geometries) is configured on its own module. It defaults to the accent, and a few of its parts borrow a look from the style.
Every knob
| Group | Knobs | Kind |
|---|---|---|
| Sizes | labels.sizeFactor, symbols.sizeFactor, roads.widthFactor | factor 0.5–1.5 |
| Typeface | labels.typeface (sans | sans-italic | serif | serif-italic) | enum |
| Map colours | colors.land, colors.water, colors.vegetation, colors.park, colors.artificial, colors.roadMajor, colors.road, colors.roadOutline, colors.label, colors.labelHalo, and colors.accent | colour |
| View | view.projection (mercator | globe) | enum |
view.sky.visible | toggle | |
view.sky.color, view.sky.horizonColor, view.space.color | colour | |
| Light | view.light.direction (0–359°), view.light.altitude (0–90°), view.light.intensity (0–1) | number |
view.light.alignment (viewport | map) | enum | |
view.light.color | colour |
The module that shows a part holds its look, which you set with the same setKnob:
| Part | Module | Its look knobs |
|---|---|---|
| Road markings | BaseMapModule | the exit numbers, arrows, restricted and under-construction roads, each shown or hidden |
| POIs | POIsModule | size, the zoom they appear at, zoom shift, label colours, micro markers |
| Traffic flow | TrafficFlowModule | the colour of each flow level, the line width and opacity |
| Traffic incidents | TrafficIncidentsModule | the colour of each severity, the line width and opacity |
| Hillshade | TerrainModule | method, light direction, strength, zoom range and colours |
The knob catalogue
stylingFoundationsKnobCatalogue lists every knob as static data, readable with no map loaded. Its entries share the shape of every module’s catalogue (Every setting as data):
import { getKnob, stylingFoundationsKnobCatalogue } from '@tomtom-org/maps-sdk/map';
for (const knob of stylingFoundationsKnobCatalogue) { // knob.id, knob.kind ('factor' | 'number' | 'toggle' | 'color' | 'enum'), knob.description, // knob.range (factor, number), knob.options (enum), knob.appliesTo const current = getKnob(styling, stylingFoundationsKnobCatalogue, knob.id);}- Entries have no
default, because the loaded style decides. On a live map,getKnobreads the value in force. stylingFoundationsKnobIdslists the ids on their own, typedStylingFoundationsKnobId.StylingFoundationsKnobValueOf<ID>is the value one takes, andstylingFoundationsKnobKindslists the kinds.- Each control of the playground at the top of this guide shows the value
getKnobreads.
Every colour a knob sets on the loaded style, whichever module holds it, also has a map-wide id. It is the module’s prefix followed by its id in that module’s catalogue. The Styling knobs keep their own ids (colors.water). The others take pois., traffic.flow., traffic.incidents. or terrain. (pois.label.color, traffic.flow.colors.slow, terrain.hillshade.colors.shaded). styleColorKnobIds lists them, typed StyleColorKnobId. getStyleColor reads the current colour of any of them (the one set, one the style derives from the map colours, or the style’s own), whether or not its module exists:
import { getStyleColor } from '@tomtom-org/maps-sdk/map';
getStyleColor(map, 'colors.water');getStyleColor(map, 'traffic.incidents.colors.major'); // undefined where the style colours it by an expressionName a map colour through them rather than hard-coding it, as the map effects plugin does to scope its bloom. StyleKnobId and StyleKnobValueOf<ID> type every style knob by its map-wide id.
When you wire controls to the catalogue, copy two things from the playground:
- Call
setKnobonce per animation frame at most. A slider or a colour picker firesinputfar faster than a restyle runs, so coalesce the calls (last value wins) and apply the final value onchange. - Rebuild the panel on external changes only.
setKnobemitsconfig-change, so rebuilding from it mid-drag replaces the input under the pointer. Skip the changes your own controls made, and rebuild on a reset, asetStyleor an agent.
Presets
A map preset is a named bundle of knob settings for a common intent. It sets knobs across the modules that hold the look of the map, which are this one, BaseMapModule’s road parts and POIsModule’s look. mapPresetCatalogue lists them with the settings each one applies, per module, by that module’s catalogue ids (MapPresetSettings):
| Preset | Intent |
|---|---|
data-viz | A quiet base for your own data on top: smaller labels and icons, thinner roads, no exit badges or road arrows, no POI dots, POIs from zoom 14 |
night-driving | Bigger labels and icons, wider roads, exit badges and road arrows shown, no POI dots, POIs from zoom 13 |
minimal | The bare map: smaller labels, no road markings or exit badges, no POI dots, POIs from zoom 16 |
globe | Globe projection with a sky |
import { applyMapPreset, setKnob, stylingFoundationsKnobCatalogue } from '@tomtom-org/maps-sdk/map';
await applyMapPreset(map, 'data-viz'); // replaces what the other presets setsetKnob(styling, stylingFoundationsKnobCatalogue, 'labels.sizeFactor', 1.1); // then adjustawait applyMapPreset(map, 'globe', { merge: true }); // lay a preset over what is thereapplyMapPresetis async, and creates the Styling, Base Map and POIs modules if the map has none yet. Theirget()returns those same instances.- By default, the knobs any preset sets are reset before this one applies, so nothing of the last preset stays. Every other knob keeps its value.
{ merge: true }skips the reset. - Whole layer groups stay as the style ships them. To hide buildings or shields, use
BaseMapModule. - An unknown id throws an
Errorlisting the known ones,mapPresetIds.MapPresetIdis their union, andMapPresetan entry of the catalogue.
A preset is exactly as durable as the knobs it sets. For the visual half of the data-viz intent, dimming and desaturating what remains, pair it with the map effects plugin’s grade and tint.
Exporting the style
exportStyle() returns the map’s style as currently rendered, as a MapLibre style specification. This is the loaded style with every knob applied, plus whatever the SDK’s data modules (places, routes) have added to it. Save it, diff it or serve it yourself.
- Tile URLs carry the API key the map was created with, so strip or rotate it before publishing the file.
map.getStyleInput()returns the style input instead, which is the id or object the map was given (Map styles).
Settings: persist, share, re-apply
getConfig() returns the overridden knobs as a plain object (StylingFoundationsModuleConfig), each nested along its id. applyConfig() replaces every knob with one, and updateConfig() replaces the top-level groups given, such as colors, and keeps the rest. It serializes cleanly, so styling can live in local storage, a URL or a pull request. It keeps working on a later SDK version for as long as the knob ids do:
localStorage.setItem('map-styling', JSON.stringify(styling.getConfig()));// …laterstyling.applyConfig(JSON.parse(localStorage.getItem('map-styling')));
styling.events.on('config-change', (settings) => save(settings));applyConfig doesn’t check what it reads back. If the settings come from somewhere you don’t control, such as a shared URL, keep them as knob values by id and restore them with setKnobs, which refuses them all if one is out of range:
setKnobs(styling, stylingFoundationsKnobCatalogue, JSON.parse(new URLSearchParams(location.search).get('styling') ?? '{}'));Style changes
The style (style on the map, or setStyle) decides which map document loads. Knobs adjust whichever one is loaded.
map.setStyle(...)re-applies the knobs once the new style has loaded, after the other modules have restored themselves, so they land on top, on the new style’s first frame.- A clean switch (
resetState: true) drops them, with the rest of the SDK state (Keeping or dropping state).
How durable is this?
There are two kinds of knobs, told apart by appliesTo in the catalogue:
any-styleknobs need no knowledge of the style, so they hold whatever the style version:- the factors, which wrap whatever the style already does;
- the
viewknobs, which set the map’s projection, sky and background rather than a layer; colors.accent, which paints no layer at all.
tomtom-stylesknobs, the ten map colours, reach their layers through a taxonomy the TomTom styles declare. The SDK re-verifies them against the styles it ships with. On a style that doesn’t declare the taxonomy, setting the knob warns once in the console and does nothing.
Nobody re-tests a setPaintProperty against a layer id when the style changes version. A knob is re-verified on every style release the SDK ships.
Interplay with other modules
Who owns what states which module owns which layers. In short:
- This module holds the foundations that reach across every part: sizes, map colours, the accent, projection and sky.
- The other style-owned modules each hold one part: whether it is shown, which of its features show and how it looks (Every knob). Where a foundation and a part’s own knob reach the same layer, they compose, and a map preset sets both at once.
- Data-owned modules (routes, places, geometries, your own GeoJSON) draw their own layers, styled through their own configuration. No knob writes them.
API reference
For complete documentation, see the StylingFoundationsModule API Reference.
Related guides and examples
Related guides
- Map colours and the accent, Map typeface, Globe and sky, Borrowed looks and Editing style layers — the features built on the knobs
- Map styles — which style loads, switching styles,
resetState - Map modules — which module owns what, and the knob catalogues every module shares
- Map Theme plugin — the map colours, accent included, from a few colours or an image
- Map effects plugin — post-processing over the frame the knobs style
- Agent Toolkit tools — the look knobs of every module as the
setMapStylingtool, presets included
Related examples
- Map styling playground — every look knob of the map on a panel built from the catalogues, and the map presets
- Themed map — a map that opens in its own colours, themed from the first frame
- Map colours — the ten map colours, each recolouring every shade derived from it
- Map typeface — every label in one typeface, from open-source font files or the style’s faces
- Map theme — the base map, an area, pins and a route themed in one call
- Four themes per style — four maps of one place side by side, moving together, with four colour themes for each standard style
- Borrowed looks — places, a route and fetched traffic incidents following the knobs that restyle the style’s POIs and incidents
- Globe and 3D terrain — the
viewknobs, then 3D terrain as you zoom in - 3D terrain playground — sky and relief that outlive a style switch