Outdoor Tags
The road layer carries the OpenStreetMap outdoor tags alongside the usual road classification, so you can filter or recolour paths by difficulty, by route network, or by what they are made of. This is the data behind the Hiking and Cycling styles, and it is available to any style you write.
None of these fields is invented or derived. They come through from OpenStreetMap as mapped, which also means coverage varies: a well-mapped alpine region will have sac_scale on most paths, and a lightly mapped one will have it on almost none. Always provide a fallback for a missing value.
Difficulty grades
| Field | Scheme | Values |
|---|---|---|
sac_scale | Swiss Alpine Club hiking scale | hiking, mountain_hiking, demanding_mountain_hiking, alpine_hiking, demanding_alpine_hiking, difficult_alpine_hiking |
mtb_scale | Mountain bike difficulty | 0 through 6 |
via_ferrata_scale | Via ferrata difficulty | easy, moderate, difficult, very_difficult, extremely_difficult |
sac_scale is the one most worth using. The step from mountain_hiking to demanding_mountain_hiking is roughly where a path stops being suitable for someone in trainers, so it is a natural place to split a trail app’s filter.
Route networks
| Field | What it is |
|---|---|
walking_network | Membership of a walking route network: iwn international, nwn national, rwn regional, lwn local |
cycling_network | The same four levels for cycle route networks: icn, ncn, rcn, lcn |
Network membership is how you tell a waymarked long-distance route from a footpath that happens to run in the same direction. The Hiking and Cycling styles use it to decide which routes get a shield and which do not.
Surface and access
| Field | What it is |
|---|---|
surface | Surface as mapped, for example asphalt, gravel, ground, rock, sand |
bicycle | Whether cycling is permitted, and how |
access | General access restrictions |
subtype | The path or way subtype, which is what the outdoor styles filter on |
Filtering by difficulty
Dim anything above a chosen grade rather than hiding it, so the map still shows that a path exists while making clear it is out of scope. Hiding it entirely tends to make people think the map is wrong.
map.addLayer({
id: 'paths-by-difficulty',
type: 'line',
source: 'mtk',
'source-layer': 'road',
filter: ['has', 'sac_scale'],
paint: {
'line-color': [
'match', ['get', 'sac_scale'],
'hiking', '#2e7d32',
'mountain_hiking', '#f9a825',
'demanding_mountain_hiking', '#ef6c00',
['alpine_hiking', 'demanding_alpine_hiking', 'difficult_alpine_hiking'], '#c62828',
'#9e9e9e'
],
'line-width': ['interpolate', ['linear'], ['zoom'], 12, 1.2, 16, 3],
'line-dasharray': [2, 1]
}
});To show only the paths a casual walker can use, filter rather than colour:
filter: ['all',
['has', 'sac_scale'],
['in', ['get', 'sac_scale'], ['literal', ['hiking', 'mountain_hiking']]]
]Route shields from the network
map.addLayer({
id: 'named-routes',
type: 'line',
source: 'mtk',
'source-layer': 'road',
// International and national routes only, which keeps a busy region readable.
filter: ['in', ['get', 'walking_network'], ['literal', ['iwn', 'nwn']]],
paint: { 'line-color': '#c2185b', 'line-width': 3, 'line-opacity': 0.7 }
});Further Reading
- Schema Reference - the full vector tile schema.
- Map Styles - the Hiking, Cycling and Winter styles that use these fields.