Maps & Geospatial Data

Permalink to "Maps & Geospatial Data"

Maps appear throughout data applications: sales by territory, stores near a customer, incidents by postcode, vehicles on a route. They are also among the least accessible interfaces on the web. A map’s information is positional and often colour-coded; its interactions are drag, scroll and click; its labels are frequently baked into image tiles. For a screen reader user, a typical map is a single unnamed object; for a keyboard user, it is a region the scroll wheel falls into and Tab cannot usefully enter.

This topic treats maps as data displays with the same obligations as charts: an equivalent that conveys the data, keyboard operation for exploring it, and names and announcements for its interactive parts. It covers choropleth (shaded region) maps, interactive pan-and-zoom maps, and marker and cluster maps. It is written for frontend engineers integrating map libraries such as Leaflet and MapLibre into data applications, and for designers deciding how geographic data should be presented.

It belongs to virtualization, charts & dynamic data displays.

WCAG criteria in scope

Permalink to "WCAG criteria in scope"
Criterion Level Relevance to maps
1.1.1 Non-text Content A A data map needs an equivalent — usually a table plus a summary
1.4.1 Use of Color A Colour bins and category colours need text or pattern equivalents
1.4.11 Non-text Contrast AA Region borders, markers and focus indicators reach 3:1
2.1.1 Keyboard A Pan, zoom and marker activation work from the keyboard
2.1.4 Character Key Shortcuts A Single-key map commands are active only while the map has focus
2.5.7 Dragging Movements AA Drag-to-pan has a single-pointer alternative
4.1.2 Name, Role, Value A Markers and clusters are named controls
4.1.3 Status Messages AA View and filter changes are announced

Prerequisites

Permalink to "Prerequisites"
Layers of an accessible map Layers of an accessible map feature: the data equivalent, the visual map with named regions and markers, the keyboard contract, the synchronised list, and the status channel. Layers of an accessible mapData equivalenttable of regions or places, plus a generated pattern summaryVisual mapnamed region or container; markers and clusters as named buttonsKeyboard contractone tab stop; arrows pan; + and − zoom; Page keys step markersSynchronised listplaces in view, sortable, linked to markersStatus channel"Zoom 10, near Utrecht, 6 stores in view"
The equivalent and the list carry the data; the map adds geography for those who can use it.

ARIA & HTML spec reference

Permalink to "ARIA & HTML spec reference"
Element / attribute Valid values When to apply Common misuse
Container role="region" + name aria-labelledby Interactive map container role="application" over the whole map
aria-describedby → instructions id Keyboard instructions for the map Instructions only in a help page
tabindex="0" on container — One tab stop for the map A tab stop per marker
Marker <button aria-label> place + fact Every interactive marker “Marker”; icon file names
Cluster <button aria-label> count + area + “expand” Marker clusters Count only as a visual number
Table with caption — Choropleth data equivalent alt describing colours
role="status" — View and filter changes Announcing on every pan frame

Step-by-step implementation

Permalink to "Step-by-step implementation"

Step 1 — Provide the data equivalent (SC 1.1.1, 1.3.1)

Permalink to "Step 1 — Provide the data equivalent (SC 1.1.1, 1.3.1)"
<table><caption>Revenue by region, Q1 2026</caption>…region, value, range, rank…</table>

Step 2 — Make the map one named tab stop (SC 2.1.1, 4.1.2)

Permalink to "Step 2 — Make the map one named tab stop (SC 2.1.1, 4.1.2)"
<div id="map" role="region" aria-labelledby="map-h" aria-describedby="map-help" tabindex="0"></div>

Step 3 — Scope pan and zoom keys (SC 2.1.1, 2.1.4)

Permalink to "Step 3 — Scope pan and zoom keys (SC 2.1.1, 2.1.4)"
el.addEventListener('keydown', (e) => { if (e.key === '+') map.zoomIn(); /* … */ });

Step 4 — Name markers and clusters (SC 4.1.2)

Permalink to "Step 4 — Name markers and clusters (SC 4.1.2)"
el.setAttribute('aria-label', `${cluster.count} stores near ${cluster.placeName}, expand`);

Step 5 — Announce settled views (SC 4.1.3)

Permalink to "Step 5 — Announce settled views (SC 4.1.3)"
map.on('moveend', debounce(() => status(describeView()), 400));
From map request to accessible map feature Flow of building an accessible map feature: define the data equivalent, choose the map type, add the keyboard contract, name interactive items, and add announcements and a list. From map request to accessible map featureData equivalenttable + summaryMap typechoropleth ormarkersKeyboardpan, zoom, stepNamesregions, markers,clustersList + statussynced, announced
The equivalent comes first — it decides what the map must add, not the other way round.

Keyboard interaction contract

Permalink to "Keyboard interaction contract"
Key Context Action Expected AT announcement Failure indicator
Tab Page Focus the map “Store locations, region” + instructions Map skipped, or a stop per marker
Arrow keys Map focused Pan After settle: view description Page scrolls instead
+ / - Map focused Zoom After settle: view description Keys fire while typing elsewhere
0 Map focused Reset view View description No way back
Page Down / Page Up Map focused Next / previous marker Marker name + “3 of 14 in view” Markers unreachable
Enter Cluster Expand “Zoomed in: 12 stores near Rotterdam.” Cluster not operable
Tab Map focused Leave the map Next control Focus trapped

Screen reader compatibility matrix

Permalink to "Screen reader compatibility matrix"
AT + browser Map container Markers as buttons View announcements
NVDA + Chrome Named region; focus mode on Tab Names read on Page-key focus Read after settle
NVDA + Firefox Same Same Same
JAWS + Chrome Named region; forms mode for keys Same Same
VoiceOver + Safari Region; VO keys may need pass-through Same May be dropped mid-animation — debounce
TalkBack + Chrome Explore by touch reaches markers Named markers readable Read
Map types and their equivalents Matrix of map types, what information each conveys, and the text or table equivalent for each. Map types and their equivalentsMap typeConveysEquivalentChoroplethValues by regionTable + pattern summaryStore or asset locatorPlaces and distancesSorted list + named markersRoute mapA sequence of stepsOrdered list of directionsHeat map (density)Intensity by areaTable of areas + summaryLive vehicle mapMoving positionsList with on-demand status
Every map type has a data shape — and that shape decides its accessible equivalent.

Edge cases & failure modes

Permalink to "Edge cases & failure modes"

1. Labels baked into tiles

Permalink to "1. Labels baked into tiles"

Diagnosis: place names exist only in raster or vector tile images. Fix: supply names in marker labels, list items and view announcements.

2. Scroll wheel captured by the map

Permalink to "2. Scroll wheel captured by the map"

Diagnosis: scrolling the page zooms the map instead. Fix: cooperative gestures or wheel zoom only after the map is engaged.

3. Re-clustering destroys focus

Permalink to "3. Re-clustering destroys focus"

Diagnosis: zooming re-forms clusters and removes the focused marker. Fix: move focus to the container or the nearest new item after re-clustering.

4. Colour-only choropleth legend

Permalink to "4. Colour-only choropleth legend"

Diagnosis: bins defined only by shade. Fix: text ranges in the legend and a Range column in the table.

5. Global single-key bindings

Permalink to "5. Global single-key bindings"

Diagnosis: the library binds + and - on the document; typing in a search box zooms the map. Fix: disable the library handler and scope keys to the focused container.

Cross-cutting concerns

Permalink to "Cross-cutting concerns"

The map is rarely the whole feature. Most maps in data applications sit next to something else: a table of regions, a list of results, a filter panel, a detail pane. Accessibility is easiest when those companions are designed as first-class views rather than afterthoughts. A store locator whose list is sortable by distance and filterable by opening hours is fully usable without the map; the map then adds orientation for users who can use it, rather than being a gate everyone must pass through.

Geography needs words. Positions on a map are meaningless to users who cannot see it unless they are expressed in terms people use: place names, distances, directions, administrative areas. Every view announcement, marker name and summary should use those terms. A reverse-geocoding step — nearest town for the map centre, neighbourhood for a marker — is often the most valuable accessibility investment on a map feature.

Library defaults vary widely. Leaflet ships keyboard panning and focusable markers with alt text options; MapLibre leaves markers entirely to you; commercial SDKs differ again. Audit the defaults of whichever library you use: whether keys are bound on the document or the container, whether markers are focusable, whether controls are buttons with names, and whether attribution links and logos are reachable.

Performance and the accessibility tree. A map with thousands of DOM markers is slow for screen readers in the same way a large table is. Clustering keeps the rendered count down; the synchronised list should be paginated or virtualised for the same reason — see pagination versus virtualization for large tables.

Motion. Animated fly-to transitions, pulsing markers and auto-panning to follow a vehicle can trigger vestibular symptoms and make it hard to keep track of focus. Respect prefers-reduced-motion by jumping instead of flying, and avoid continuous animation of markers.

Touch screen readers. VoiceOver on iOS and TalkBack on Android let users explore the map by touch, which reaches DOM markers but not tile content. Named markers and a list view are what make touch exploration productive; pinch-zoom gestures are handled by the screen reader and should not be relied on as the only way to zoom.

Choropleth table alternatives

Permalink to "Choropleth table alternatives"

Table alternatives for choropleth maps builds the region table, writes colour bins as text, and generates a summary of extremes and geographic patterns from the same data as the map.

summarise(rows, regionMeta);   // "North highest at €410k; 1 region in the high band."

Behaviour note: sorting by value by default puts the map’s main message first.

Keyboard panning and zooming

Permalink to "Keyboard panning and zooming"

Keyboard panning and zooming for interactive maps gives the map one tab stop, scoped arrow and zoom keys, visible buttons, a scroll-wheel fix, and a settled view description.

map.on('moveend', debounce(describeView, 400));

Behaviour note: avoid role="application"; scoped keys on a named region give control without removing reader commands.

Markers and clusters

Permalink to "Markers and clusters"

Announcing map markers and clusters turns markers and clusters into named buttons, steps through them nearest-first, and synchronises the map with a list of places in view.

el.setAttribute('aria-label', `${store.name}, ${store.openText}`);

Behaviour note: the list is usually the fastest way to browse; the map answers spatial questions.

Steps to reach the nearest open store Bar chart comparing the actions needed to reach the nearest open store in an example locator with 60 markers: tabbing through every marker, stepping nearest-first on the map, and using a sorted, filtered list. Steps to reach the nearest open storeTab through every marker60 actions — map as a keyboard trapPage Down, nearest first4 actionsFilter "open", list sorted bydistance2 actions
In an example locator with 60 stores, a sorted and filtered list gets there in two steps.

Who these decisions affect

Permalink to "Who these decisions affect"

Blind and low-vision users get the data from the equivalent: the table, the summary, the list. For many, the map adds little; for others with some vision, it adds geography once they can pan and zoom it.

Keyboard-only users need the map to be reachable, operable and escapable, and markers to be reachable without dozens of Tab presses.

Users of screen magnifiers see a small window of the map; view announcements and a list keep them oriented when they cannot see the whole map at once.

Colour-vision deficiency affects choropleth reading directly; text ranges and patterns make the classification available without colour.

Where to start on an existing map feature

Permalink to "Where to start on an existing map feature"

Maps are often built once and left alone, so the retrofit order matters:

  1. The equivalent. Add the table (for choropleths) or the list (for markers) first. It is plain HTML, it helps every user, and it makes the feature usable by screen reader users immediately, whatever state the map is in.
  2. The name and instructions. Give the map container a name and a short line of keyboard instructions linked with aria-describedby.
  3. Scoped keys. Check where the library binds its keyboard handler. If it is on the document, turn it off and install your own on the container.
  4. Zoom buttons. Make sure zoom in, zoom out and reset are real, named buttons — some libraries render them as links or unnamed icons.
  5. Markers. Turn markers into named buttons without tab stops and add Page-key stepping.
  6. Announcements. Add the debounced view description, then cluster and filter messages.

Steps one and two alone move a map from unusable to usable for most screen reader users; steps three to six make the map itself explorable for keyboard users.

Design system integration

Permalink to "Design system integration"
Component Accessible behaviour Criterion
MapContainer Named region, instructions, scoped keys, controls, settle announcements 2.1.1, 2.1.4, 4.1.3
Marker / Cluster factories Named buttons, no tab stop, stepping order 4.1.2, 2.4.3
MapList Synchronised list of items in view 1.1.1, 1.3.1
ChoroplethTable Region table with text bins and generated summary 1.1.1, 1.4.1
Map tokens Borders, markers and focus at 3:1 in both themes 1.4.11

Testing checklist

Permalink to "Testing checklist"

Automated

Permalink to "Automated"

Keyboard

Permalink to "Keyboard"

Screen reader

Permalink to "Screen reader"

FAQ

Permalink to "FAQ"
How do I make a map accessible to screen reader users?

Provide the map’s data in an accessible form — a table of regions and values or a list of places — with a short summary of the pattern, and make the interactive map itself keyboard operable with named markers and announced view changes.

Is alt text enough for a data map?

No. A name or description of the picture does not give users the values. The data behind the map, as a table or list, is the equivalent.

Do map tiles need text alternatives?

The tiles themselves are background imagery and can be treated as decorative, but any information they carry that users need — place names, boundaries, points of interest — must be available in text through markers, lists or announcements.

How should a route map be made accessible?

Provide the route as an ordered list of steps with distances and turn directions, and keep it synchronised with the highlighted segment on the map. The list is the primary way to follow a route by keyboard or screen reader.

Can a map be the only way to find a location?

It should not be. Offer search by name or postcode and a sortable list, so users who cannot operate or see the map can still find what they need directly.

Should maps use role="application"?

Usually not. Use a named region with keyboard handling scoped to the focused map, so screen reader users keep their reading commands.

Permalink to "Related"

← Back to Virtualization, Charts & Dynamic Data Displays