mgunyho
(Marton)
July 24, 2025, 1:26pm
1
At this location: OpenStreetMap the highway is rendered on top of the overpass in Shortbread:
In the standard and other styles it is correct, except for MapTiler OMT, which looks similar to the Shortbread. (I cannot post another screenshot because my account is new.)
As far as I can tell, the map data is correct, the highway is layer 1 while the overpass is layer 2. Is this a bug in the vector style?
mgunyho
(Marton)
July 24, 2025, 1:31pm
2
I just realized that it might be because the lane on the left turns into a bridge just south of the overpass, while the right lane becomes a bridge slightly to the north, and the bridge is apparently rendered on top of the overpass even if it is on a layer below it.
1 Like
Richard
(Richard Fairhurst)
July 24, 2025, 1:37pm
3
Layer ordering is a long-standing issue with vector tiles and not yet practically solved (aside from some ugly hacks). It really needs client support in the MapLibre renderer and there are active tickets for that:
opened 02:46AM - 30 Jan 23 UTC
enhancement
## Motivation
The OSM Americana project would like to efficiently and properl… y render "stacked" bridges and tunnels, in which multiple bridges or tunnels overlap each other. This occurs in large dense cities.
While there is currently a [line-sort-key](https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#layout-line-line-sort-key) in the style specification, this only works on a _single_ layer. In order to draw the various combinations of road, bridge, and tunnel, we are rendering a casing, a fill, sometimes a casing dash pattern, and sometimes an inner fill dash pattern. It is not currently possible in the style spec to merge all these together into a single layer, and thus each component of the style must be rendered as a separate layer.
What is needed is a group-line-sort-key in order to apply the sort-key logic across a consecutive group of layers.
For example, this location in Boston has several overlapping bridges:
[](https://zelonewolf.github.io/openstreetmap-americana/#map=17/42.370104/-71.064875)
The overlap is indicated with tagging of `layer`. So the first bridge might be `layer=1`, the second bridge is `layer=2` and so forth.
Stacked roads are represented in vector tiles with an attribute that indicates the z-order of each road:

The desired end-state looks something like this, where the roads are drawn casing-fill-casing-fill-casing-fill for each layer. This is outlined in https://github.com/maplibre/maplibre-gl-js/issues/2108#issuecomment-1409278734:

Currently, the only way to do this is to repeat the _entire_ road layer for `layer=1`, `layer=2`, etc., up to some value of **N** where nobody has mapped two or more overlapping roads with a value of `layer` that's greater than N. In practice, 5 layers should cover all cases on earth for roads (as of 2023). However, there's no guarantee that mappers use small values of `layer` -- the only thing that you can count on is the ordering. This is the [hack currently used](https://github.com/ZeLonewolf/openstreetmap-americana/blob/9e85aa4b1327b878e3f0d0bb0e89d12290d48353/src/layer/rail.js#L429-L450) in the OSM Americana project.
In Sydney, Australia there's a series of similarly overlapping tunnels. However, these do not overlap properly (ZeLonewolf/openstreetmap-americana#27) -- the layer values descend to -4, -5, etc., well beyond that style's assumed limit of -2 for tunnels (after all -- how stacked could tunnels possibly be?).
[](https://zelonewolf.github.io/openstreetmap-americana/#map=18/-33.87439/151.218122)
Duplicating the entire transportation layer code to achieve bridge/tunnel layering is, a MASSIVE inflation of the layer count, and one of the reasons that the OSM Americana [style.json](https://zelonewolf.github.io/openstreetmap-americana/style.json) is nearly a megabyte in size and most certainly is a performance problem.
## Usage
Ideally, We would like to be able to specify that a group of layers should obey a sort-order key, where multiple passes are made across the group of layers, rendering one layer value at a time until all layer values are exhausted. It's sufficient to assume that the group of layers are all consecutive.
3 Likes