Skip to content
Outdoor Tags

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

FieldSchemeValues
sac_scaleSwiss Alpine Club hiking scalehiking, mountain_hiking, demanding_mountain_hiking, alpine_hiking, demanding_alpine_hiking, difficult_alpine_hiking
mtb_scaleMountain bike difficulty0 through 6
via_ferrata_scaleVia ferrata difficultyeasy, 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

FieldWhat it is
walking_networkMembership of a walking route network: iwn international, nwn national, rwn regional, lwn local
cycling_networkThe 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

FieldWhat it is
surfaceSurface as mapped, for example asphalt, gravel, ground, rock, sand
bicycleWhether cycling is permitted, and how
accessGeneral access restrictions
subtypeThe 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