<div><span class="lbl">City guide with custom pins and popups</span>
<section class="lf" aria-labelledby="lf-guide-title">
<h2 id="lf-guide-title">An afternoon in central Lisbon</h2>
<p class="lf-sub">Five stops within a 40-minute walk. Select a pin for details.</p>
<div class="lf-map" data-leaflet role="region" aria-label="Map of central Lisbon with five places"></div>
<script type="application/json">[{"name":"Castelo de São Jorge","note":"Moorish castle walls and the city’s highest lookout.","lat":38.7139,"lng":-9.1335,"type":"sight"},
{"name":"Miradouro de Santa Luzia","note":"Tiled terrace over the rooftops of Alfama.","lat":38.7118,"lng":-9.1302,"type":"view"},
{"name":"Praça do Comércio","note":"Riverside square at the foot of Rua Augusta.","lat":38.7075,"lng":-9.1364,"type":"sight"},
{"name":"Mercado da Ribeira","note":"Covered market and food hall by Cais do Sodré.","lat":38.7068,"lng":-9.1458,"type":"food"},
{"name":"Jardim do Príncipe Real","note":"Shady garden with a giant cedar and kiosk café.","lat":38.7166,"lng":-9.1484,"type":"view"}]</script>
<ul class="lf-legend"><li><span class="lf-swatch" style="background:#7c3aed" aria-hidden="true"></span>Sights</li><li><span class="lf-swatch" style="background:#be123c" aria-hidden="true"></span>Viewpoints</li><li><span class="lf-swatch" style="background:#0f766e" aria-hidden="true"></span>Food</li></ul>
<p class="lf-keys">Keyboard: Tab to the map, then use the arrow keys to pan and + or − to zoom. Tab again to reach each pin; Enter opens its card.</p>
</section></div>
<div><span class="lbl">Map with a list that shows each place</span>
<section class="lf" data-leaflet-box aria-labelledby="lf-week-title">
<h2 id="lf-week-title">Lisbon Design Week venues</h2>
<p class="lf-sub">Four venues, 14–17 May. Choose one to centre it on the map.</p>
<div class="lf-split">
<ul class="lf-list">
<li><button class="lf-item" type="button" data-place="0" aria-pressed="false"><strong>Riverside Pavilion</strong><small>Thu 14 May · Talks and the opening night. Belém, by the river.</small></button></li>
<li><button class="lf-item" type="button" data-place="1" aria-pressed="false"><strong>Factory Courtyard</strong><small>Fri 15 May · Studio open days in a former textile mill.</small></button></li>
<li><button class="lf-item" type="button" data-place="2" aria-pressed="false"><strong>Design Museum, Baixa</strong><small>Sat 16 May · Exhibition: forty years of Portuguese chairs.</small></button></li>
<li><button class="lf-item" type="button" data-place="3" aria-pressed="false"><strong>Garden Auditorium</strong><small>Sun 17 May · Closing panel and awards in the park.</small></button></li>
</ul>
<div>
<div class="lf-map" data-leaflet role="region" aria-label="Map of the four Design Week venues"></div>
<script type="application/json">[{"name":"Riverside Pavilion","note":"Talks and the opening night. Belém, by the river.","lat":38.6957,"lng":-9.1923,"type":"sight","when":"Thu 14 May"},
{"name":"Factory Courtyard","note":"Studio open days in a former textile mill.","lat":38.7034,"lng":-9.1785,"type":"food","when":"Fri 15 May"},
{"name":"Design Museum, Baixa","note":"Exhibition: forty years of Portuguese chairs.","lat":38.7095,"lng":-9.1373,"type":"view","when":"Sat 16 May"},
{"name":"Garden Auditorium","note":"Closing panel and awards in the park.","lat":38.7372,"lng":-9.1546,"type":"sight","when":"Sun 17 May"}]</script>
</div>
</div>
</section></div>
<div><span class="lbl">City guide with custom pins and popups</span>
<section class="lf card rounded-4 p-3 p-sm-4" aria-labelledby="lf-guide-title">
<h2 id="lf-guide-title" class="h4 fw-bold mb-1">An afternoon in central Lisbon</h2>
<p class="lf-sub text-body-secondary mb-3">Five stops within a 40-minute walk. Select a pin for details.</p>
<div class="lf-map" data-leaflet role="region" aria-label="Map of central Lisbon with five places"></div>
<script type="application/json">[{"name":"Castelo de São Jorge","note":"Moorish castle walls and the city’s highest lookout.","lat":38.7139,"lng":-9.1335,"type":"sight"},
{"name":"Miradouro de Santa Luzia","note":"Tiled terrace over the rooftops of Alfama.","lat":38.7118,"lng":-9.1302,"type":"view"},
{"name":"Praça do Comércio","note":"Riverside square at the foot of Rua Augusta.","lat":38.7075,"lng":-9.1364,"type":"sight"},
{"name":"Mercado da Ribeira","note":"Covered market and food hall by Cais do Sodré.","lat":38.7068,"lng":-9.1458,"type":"food"},
{"name":"Jardim do Príncipe Real","note":"Shady garden with a giant cedar and kiosk café.","lat":38.7166,"lng":-9.1484,"type":"view"}]</script>
<ul class="list-inline small text-body-secondary mt-3 mb-0"><li class="list-inline-item d-inline-flex align-items-center gap-2 me-3"><span class="lf-swatch" style="background:#7c3aed" aria-hidden="true"></span>Sights</li><li class="list-inline-item d-inline-flex align-items-center gap-2 me-3"><span class="lf-swatch" style="background:#be123c" aria-hidden="true"></span>Viewpoints</li><li class="list-inline-item d-inline-flex align-items-center gap-2 me-3"><span class="lf-swatch" style="background:#0f766e" aria-hidden="true"></span>Food</li></ul>
<p class="small text-body-secondary mt-2 mb-0">Keyboard: Tab to the map, then use the arrow keys to pan and + or − to zoom. Tab again to reach each pin; Enter opens its card.</p>
</section></div>
<div><span class="lbl">Map with a list that shows each place</span>
<section class="lf card rounded-4 p-3 p-sm-4" data-leaflet-box aria-labelledby="lf-week-title">
<h2 id="lf-week-title" class="h4 fw-bold mb-1">Lisbon Design Week venues</h2>
<p class="lf-sub text-body-secondary mb-3">Four venues, 14–17 May. Choose one to centre it on the map.</p>
<div class="row g-3">
<div class="col-12 lf-side">
<ul class="list-unstyled d-grid gap-2 mb-0">
<li><button class="lf-item list-group-item list-group-item-action d-grid gap-1 px-3 py-2" type="button" data-place="0" aria-pressed="false"><strong>Riverside Pavilion</strong><small class="text-body-secondary">Thu 14 May · Talks and the opening night. Belém, by the river.</small></button></li>
<li><button class="lf-item list-group-item list-group-item-action d-grid gap-1 px-3 py-2" type="button" data-place="1" aria-pressed="false"><strong>Factory Courtyard</strong><small class="text-body-secondary">Fri 15 May · Studio open days in a former textile mill.</small></button></li>
<li><button class="lf-item list-group-item list-group-item-action d-grid gap-1 px-3 py-2" type="button" data-place="2" aria-pressed="false"><strong>Design Museum, Baixa</strong><small class="text-body-secondary">Sat 16 May · Exhibition: forty years of Portuguese chairs.</small></button></li>
<li><button class="lf-item list-group-item list-group-item-action d-grid gap-1 px-3 py-2" type="button" data-place="3" aria-pressed="false"><strong>Garden Auditorium</strong><small class="text-body-secondary">Sun 17 May · Closing panel and awards in the park.</small></button></li>
</ul>
</div>
<div class="col-12 lf-main">
<div class="lf-map" data-leaflet role="region" aria-label="Map of the four Design Week venues"></div>
<script type="application/json">[{"name":"Riverside Pavilion","note":"Talks and the opening night. Belém, by the river.","lat":38.6957,"lng":-9.1923,"type":"sight","when":"Thu 14 May"},
{"name":"Factory Courtyard","note":"Studio open days in a former textile mill.","lat":38.7034,"lng":-9.1785,"type":"food","when":"Fri 15 May"},
{"name":"Design Museum, Baixa","note":"Exhibition: forty years of Portuguese chairs.","lat":38.7095,"lng":-9.1373,"type":"view","when":"Sat 16 May"},
{"name":"Garden Auditorium","note":"Closing panel and awards in the park.","lat":38.7372,"lng":-9.1546,"type":"sight","when":"Sun 17 May"}]</script>
</div>
</div>
</section></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#475569] uppercase">City guide with custom pins and popups</span>
<section class="rounded-[22px] border border-[#e2e8f0] bg-white p-4 text-[#0f172a] sm:p-6" aria-labelledby="lf-guide-title">
<h2 id="lf-guide-title" class="text-[1.3rem] font-bold tracking-[-.02em]">An afternoon in central Lisbon</h2>
<p class="mt-1 mb-4 text-[.92rem] text-[#475569]">Five stops within a 40-minute walk. Select a pin for details.</p>
<div class="lf-map" data-leaflet role="region" aria-label="Map of central Lisbon with five places"></div>
<script type="application/json">[{"name":"Castelo de São Jorge","note":"Moorish castle walls and the city’s highest lookout.","lat":38.7139,"lng":-9.1335,"type":"sight"},
{"name":"Miradouro de Santa Luzia","note":"Tiled terrace over the rooftops of Alfama.","lat":38.7118,"lng":-9.1302,"type":"view"},
{"name":"Praça do Comércio","note":"Riverside square at the foot of Rua Augusta.","lat":38.7075,"lng":-9.1364,"type":"sight"},
{"name":"Mercado da Ribeira","note":"Covered market and food hall by Cais do Sodré.","lat":38.7068,"lng":-9.1458,"type":"food"},
{"name":"Jardim do Príncipe Real","note":"Shady garden with a giant cedar and kiosk café.","lat":38.7166,"lng":-9.1484,"type":"view"}]</script>
<ul class="mt-3 flex flex-wrap gap-x-[18px] gap-y-1.5 text-[.82rem] text-[#475569]"><li class="flex items-center gap-[7px]"><span class="lf-swatch" style="background:#7c3aed" aria-hidden="true"></span>Sights</li><li class="flex items-center gap-[7px]"><span class="lf-swatch" style="background:#be123c" aria-hidden="true"></span>Viewpoints</li><li class="flex items-center gap-[7px]"><span class="lf-swatch" style="background:#0f766e" aria-hidden="true"></span>Food</li></ul>
<p class="mt-2 text-[.8rem] text-[#475569]">Keyboard: Tab to the map, then use the arrow keys to pan and + or − to zoom. Tab again to reach each pin; Enter opens its card.</p>
</section></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#475569] uppercase">Map with a list that shows each place</span>
<section class="rounded-[22px] border border-[#e2e8f0] bg-white p-4 text-[#0f172a] sm:p-6" data-leaflet-box aria-labelledby="lf-week-title">
<h2 id="lf-week-title" class="text-[1.3rem] font-bold tracking-[-.02em]">Lisbon Design Week venues</h2>
<p class="mt-1 mb-4 text-[.92rem] text-[#475569]">Four venues, 14–17 May. Choose one to centre it on the map.</p>
<div class="grid gap-[18px] min-[860px]:grid-cols-[280px_minmax(0,1fr)]">
<ul class="grid content-start gap-2">
<li><button class="grid w-full cursor-pointer gap-0.5 rounded-[14px] border border-[#e2e8f0] bg-white px-3.5 py-3 text-left transition-colors hover:border-[#94a3b8] hover:bg-[#f8fafc] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] aria-pressed:border-[#0f172a] aria-pressed:shadow-[inset_0_0_0_1px_#0f172a] motion-reduce:transition-none" type="button" data-place="0" aria-pressed="false"><strong>Riverside Pavilion</strong><small class="text-[.8rem] text-[#475569]">Thu 14 May · Talks and the opening night. Belém, by the river.</small></button></li>
<li><button class="grid w-full cursor-pointer gap-0.5 rounded-[14px] border border-[#e2e8f0] bg-white px-3.5 py-3 text-left transition-colors hover:border-[#94a3b8] hover:bg-[#f8fafc] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] aria-pressed:border-[#0f172a] aria-pressed:shadow-[inset_0_0_0_1px_#0f172a] motion-reduce:transition-none" type="button" data-place="1" aria-pressed="false"><strong>Factory Courtyard</strong><small class="text-[.8rem] text-[#475569]">Fri 15 May · Studio open days in a former textile mill.</small></button></li>
<li><button class="grid w-full cursor-pointer gap-0.5 rounded-[14px] border border-[#e2e8f0] bg-white px-3.5 py-3 text-left transition-colors hover:border-[#94a3b8] hover:bg-[#f8fafc] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] aria-pressed:border-[#0f172a] aria-pressed:shadow-[inset_0_0_0_1px_#0f172a] motion-reduce:transition-none" type="button" data-place="2" aria-pressed="false"><strong>Design Museum, Baixa</strong><small class="text-[.8rem] text-[#475569]">Sat 16 May · Exhibition: forty years of Portuguese chairs.</small></button></li>
<li><button class="grid w-full cursor-pointer gap-0.5 rounded-[14px] border border-[#e2e8f0] bg-white px-3.5 py-3 text-left transition-colors hover:border-[#94a3b8] hover:bg-[#f8fafc] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] aria-pressed:border-[#0f172a] aria-pressed:shadow-[inset_0_0_0_1px_#0f172a] motion-reduce:transition-none" type="button" data-place="3" aria-pressed="false"><strong>Garden Auditorium</strong><small class="text-[.8rem] text-[#475569]">Sun 17 May · Closing panel and awards in the park.</small></button></li>
</ul>
<div>
<div class="lf-map" data-leaflet role="region" aria-label="Map of the four Design Week venues"></div>
<script type="application/json">[{"name":"Riverside Pavilion","note":"Talks and the opening night. Belém, by the river.","lat":38.6957,"lng":-9.1923,"type":"sight","when":"Thu 14 May"},
{"name":"Factory Courtyard","note":"Studio open days in a former textile mill.","lat":38.7034,"lng":-9.1785,"type":"food","when":"Fri 15 May"},
{"name":"Design Museum, Baixa","note":"Exhibition: forty years of Portuguese chairs.","lat":38.7095,"lng":-9.1373,"type":"view","when":"Sat 16 May"},
{"name":"Garden Auditorium","note":"Closing panel and awards in the park.","lat":38.7372,"lng":-9.1546,"type":"sight","when":"Sun 17 May"}]</script>
</div>
</div>
</section></div>
The one set in this pack that uses a map library: Leaflet 1.9.4, loaded from jsDelivr with pinned versions and subresource integrity, with OpenStreetMap tiles and the required attribution. No API key is needed. The first map is a city guide of central Lisbon with five places; each uses a custom L.divIcon pin in the style of set 05, coloured by type with a legend, and opens a popup with a short note and a directions link. The second map sits beside a list of four event venues; choosing a venue in the list centres the map on it and opens its popup, which gives keyboard and screen reader users a simple way through the places. Place data lives in a small JSON script next to each map, so you edit names and coordinates without touching the script. Scroll-wheel zoom is off so the page scrolls normally, the map fits itself to its markers, and zoom and fade animations are turned off for visitors who prefer reduced motion. Below the first map, a short note explains the keyboard controls. Check the OpenStreetMap tile usage policy before heavy production use, or point the tile URL at your own provider.
What’s included
Leaflet 1.9.4 pinned with subresource integrity
OpenStreetMap tiles with attribution and no API key
Custom divIcon pins that match the marker set
Places read from an editable JSON script
List of venues that centres the map and opens popups
Accessibility
Each map container is a labelled region that Leaflet makes keyboard-operable: arrow keys pan and plus and minus zoom. Every pin is focusable, named by its title, and opens its popup with Enter. Directions links in popups name their place and say they open a new tab. Focus outlines are added for the map, pins and controls, the list buttons use aria-pressed, and Leaflet's zoom and fade animations are disabled under prefers-reduced-motion.
Customise it
Edit the colours object in the script for pin colours and the .lf-map rules for height, radius and popup styling. Change the JSON places, or the tile URL and attribution if you use another tile provider.