I want to use Bootstrap Icons for the map markers in Leaflet. There are a number of plugin libraries for this (e.g. [1], [2], [3]), but they’re unmaintained or don’t work with the latest Bootstrap Icons.
So I tried to do this from scratch, using inline SVG rather than separate images. I took the SVG map pin “balloon” from here, and added the icon above it using absolute positioning.
const map = L.map('map').setView([51.505, -0.09], 8);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
const icon = L.divIcon({
html: `
<div>
<svg width="25px" height="41px" viewBox="0 0 32 52" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M16,1 C7.7146,1 1,7.65636364 1,15.8648485 C1,24.0760606 16,51 16,51 C16,51 31,24.0760606 31,15.8648485 C31,7.65636364 24.2815,1 16,1 L16,1 Z"></path>
</svg>
<i class="bi bi-house-fill"></i>
</div>`,
iconSize: [41, 52],
className: 'icon'
});
L.marker([51.5, -0.09]).addTo(map);
L.marker([51.5, -0.09], { icon: icon }).addTo(map);
.icon { position: relative; }
.icon path { fill: var(--bs-primary); stroke: var(--bs-dark); }
.bi { position: absolute; top: 1px; left: 4px; font-size: 1rem; color: var(--bs-light); }
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" /></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<div class="vw-100 vh-100 d-flex">
<div id="map" class="flex-grow-1"></div>
</div>
The result is not as pretty as the the library itself or as the old library plugins, but good enough… However I need to manually tweak each icon (css top
/ left
) to fit inside the balloon.
There are some issues:
- The marker has no shadow; do I need to do this myself or is it done via leaflet?
- The marker is offset: in the demo, notice how both markers are placed on the same point, but the custom one is offset.