Optimize map label placement
Map labels are applied to Mapbox GL maps as features in symbol layers. Symbol layers are the most complex layer type in the Mapbox Style Specification. The symbol layer type offers detailed typographic styling options for your labels and map data.
This guide will walk through a subset of layout properties that are relevant to label placement. You can see the complete list of layout and paint properties for symbol layers, including those responsible for label language, style, and more, in the Mapbox Style Specification.
Collision detection is the process of preventing labels on a map from overlapping each other. Styles use four properties to prevent label collision:
- By default
text-allow-overlapare set to
false. If set to
true, the icon or text will be visible even if it collides with other symbols drawn before.
- By default
text-ignore-placementare set to
false. If set to
true, other symbols can be visible even if they collide with the text or icon.
For reliable collision detection across layers that come from different data sources, use source compositing. Source compositing happens by default for new styles created in Mapbox Studio. If you are adding sources on the client, they will not be composited.
While detecting and preventing label collision helps improve map legibility, it can result in many hidden labels. Use collision detection and variable label placement to keep labels legible while increasing the density of labels displayed on the map.
Variable label placement is a map design concept in which more than one placement option is attempted for each label. This maximizes the chances that the map will show each label. Variable label placement is powered by three layout properties in the Mapbox Style Specification:
The digaram below illustrates each possible position relative to the data point:
text-variable-anchor accepts an array of text-anchor positions as the input value. The map renderer tries to place the label at the positions in this list in the provided order of the array at collision detection time.
For example, in a layer with
text-variable-anchor set to
["top", "bottom", "left"], the map renderer would first try to place each label anchored at the top. Then, if there wasn't room for the label at that position, it would try to place the label anchored at the bottom. And finally, if the label could not fit on the map anchored at the top or bottom, it would try anchoring on the left side. If none of these anchor positions can be used, the map will not display the label.
If a user changes the map zoom after a label has been placed, the map renderer will try to place the label in its original position first before moving on to the rest of the positions specified in the
text-variable-anchor array. This exception makes map rendering more efficient, but can sometimes be surprising.
The order in which each label in a layer will go through this process is described in detail below in Label hierarchy.
text-radial-offset accepts a scalar value that represents the offset distance of text from its anchor and is applied to the
text-variable-anchor. Positive values specify right and down, while negative values specify left and up.
text-justify specifies the justification of the label. It can be set to one of
auto will automatically set the justification towards the anchor position.
Some labels on your map may be more relevant to a wider audience or more important to a particular audience. When two labels collide, the draw order of features determines which label to display and which to hide. There are several factors that contribute to draw order.
Map styles contain a collection of style layers. Layers are specified in your style JSON and are drawn in order. This means that the first layer defined in the style JSON will be drawn first and will appear below all layers that follow. The last layer defined in the style JSON will be drawn last, on top of all other layers.
You can increase the chances that a layer's labels will be visible by placing that layer further down in your style JSON.
For each layer in your style, you must specify a source. For vector sources, you must also specify a source layer for each style layer. The draw order of features inside a single vector tileset source layer can be specified in two ways:
- At the time of tileset creation: If you are using the Mapbox Tilesets API, you can specify the order of features inside a single source layer using the
orderoption. See the Tilesets API recipe reference.
- At runtime with
symbol-sort-key: If you don't have control over the data at the time of tileset creation, you can influence the draw order of features at runtime using
For GeoJSON sources, the draw order of features is determined by the order of features in the feature collection. Features are draw in descending order.