Quick Fix · Life Hacks · Content

Your Store Locator Map Is Invisible to Screen Reader Users. Here's the List-View Fix.

Illustration of a map with several pin markers beside a simple bulleted list of addresses, in an oxblood and cream editorial style
  • Quick Fix
  • Life Hacks
  • Content

Turn on a screen reader right now and try to find your nearest store using only your own store locator page. Go ahead, we'll wait. If all you heard was "map, graphic" — maybe a stray "application" if it's an interactive embed — and then silence, congratulations: your addresses, phone numbers, and hours exist in exactly one place, and it's a place a screen reader user can't reach.

Here's the good news. This is one of the fastest, cheapest fixes in all of accessibility. You don't have to rebuild your map, swap vendors, or touch a single line of the mapping library's code. You just have to stop treating the map as the only interface and add the plain-text one that should've been sitting next to it all along.

The Stat: WCAG SC 1.1.1 Non-text Content (Level A) requires a text alternative that serves the equivalent purpose for non-text content — an embedded interactive map, being a complex, purely visual interface, needs an equivalent way to get the same information, which for a store locator is most practically a real, readable list of the same addresses/hours/phone numbers next to the map, not inside it. (Source: W3C WCAG 2.1)

Map Only vs. Map Plus List Left panel shows a plain map rectangle with four unlabeled pin icons and no text, labeled MAP ONLY. Right panel shows the same map rectangle beside a three-line text list representing address, phone, and hours, labeled MAP + LIST.

MAP ONLY "map, graphic" — that's all a screen reader hears

MAP + LIST 123 Main St (555) 010-2200 Mon-Sat 9-8 3 more locations Same pins, plus a list anyone can actually read

Why the map alone can never be "accessible enough"

A store locator map is a genuinely hard case for accessibility, and it's worth being honest about why. Pins are rendered on a canvas or tile layer. Their position is meaningful only visually — proximity to a highway, distance from downtown, clustering in a neighborhood. None of that translates to a screen reader's linear, one-item-at-a-time reading model. Even if you slap alt="" or aria-label="map" on the container, you've described the box, not the contents.

This isn't a reason to give up on the map. It's a reason to stop asking the map to do a job it structurally cannot do. The W3C WAI tutorial on complex images makes this exact point about any visual that encodes real information: charts, diagrams, and yes, maps, need a short text alternative and a long-form equivalent that conveys the actual data. For a store locator, that long-form equivalent isn't a paragraph — it's a list.

The fix: a list view that lives beside the map, not inside it

The pattern is simple enough to ship this week:

  1. Keep the map. Sighted users who navigate visually still benefit from it — this isn't about removing a feature.
  2. Add a real, semantic list of every location the map shows. Each entry gets the store name, full address, phone number, and hours, marked up as actual text (a heading or <dt>, plus paragraphs or a definition list) — not an image, not a tooltip that only appears on hover.
  3. Make the list load with the page, not only after a map interaction. If your map lazy-loads pins based on viewport, the list should populate from the same data source independent of whether the map has finished rendering.
  4. Sync selection both ways. Clicking a list item should pan/highlight the matching pin; where feasible, activating a pin should scroll to and focus the matching list entry. This isn't required by 1.1.1 itself, but it's the detail that makes the two views feel like one coherent tool instead of two disconnected features.
  5. Label the map region. Give the map container a landmark or aria-label (e.g., "Map of store locations — see list below for full details") so screen reader users know it exists and know exactly where the equivalent lives, instead of wondering if they're missing something.
Map-only pattern Map + list pattern
Address only exists as pin metadata in a popup Address is real, readable text on the page
Screen reader announces "map" or "application" and stops Screen reader reads store name, address, phone, hours in order
Keyboard users can't tab to individual locations Keyboard users tab through list items like any other links
Zero text for search engines to index per location Each location's info is crawlable, indexable content

That last row is a nice side effect: the same list that fixes your accessibility gap also gives you real per-location content instead of a black box full of pins.

Quick self-check before you ship

  • Every pin on the map has a matching entry in a text list on the same page
  • The list includes name, address, phone, and hours — not just a "view details" link
  • The list is real DOM text, not an image or a canvas label
  • The map container has a label explaining what it is and that a list follows
  • List and map stay in sync if a user filters by city, zip, or radius

If you're leaning on a third-party map embed rather than building your own pin logic, it's worth knowing that Google's own accessibility support page for Google Maps documents built-in screen reader and keyboard support for their embeds — useful context if you're troubleshooting which parts of your locator are your responsibility to fix versus which are inherited from the underlying map provider. Either way, per WCAG 1.1.1 Non-text Content, the equivalent-text obligation sits with your page, not the map vendor.

Don't forget "Get Directions"

One detail teams consistently miss once the list view is in place: the "Get Directions" link. On a map-only locator, directions usually only work by clicking a pin, which means the whole feature inherits every accessibility problem the map already has. Once you've built a real list, this is nearly free to fix — each list entry just needs its own plain-text "Get directions" link pointing to a standard maps URL (Google Maps, Apple Maps, or whichever service you use) built from that location's actual address string. No JavaScript pin-click handler required, no dependency on the map having rendered at all. A keyboard user can tab straight to it; a screen reader user hears exactly which location it's for, because it's sitting right next to that location's name and address in the list, not floating inside a popup bubble they may never discover.

One more thing: don't gate the list behind the map's load state

A subtle version of this bug survives even after teams add a list view: if the list only populates once the map's JavaScript has finished loading and geocoding pins, a slow connection, a blocked third-party script, or an ad blocker that flags the map provider can leave the list empty right alongside a broken or missing map — the worst of both worlds. Pull your location data (name, address, phone, hours) from the same source file or API response for both the map and the list, and render the list independently of whether the map script has loaded at all. That way a map failure degrades to "no map, but a perfectly usable list," instead of "nothing works."

The myth worth busting

"Our map has a search bar and address input, so it's interactive and accessible." Interactive isn't the same as perceivable. A user who can't see the pins can't benefit from a search bar that only surfaces results on the map — unless those results also land in a real, readable list. Interactivity without an equivalent output is still a dead end.

Store locators are exactly the kind of page nobody audits until it's the one blocking a customer from finding your nearest location — and it's a fast, low-drama fix once you see it. Curious what else on your site is quietly map-only? Find out with a free automated scan and see what it turns up on your own location pages.