Images over a Map Image

Hello!

I’ve been using Rapidweaver for years and recently switched to Elements. I’m really enjoying the flexibility. I have some technical experience but I’d say I’ve mostly used Themes in the past and this is my first time setting up a from scratch.

I’m building a website for my author wife and she’s requested a map with the locations of her books superimposed on top of it. I’ve managed to get it working, links to each book and a little scale/rotate animation when hovering, but have run into a couple problems:

  1. I used the Transforms option to place the images (book covers) in the correct place on the map but they drift when I change to different breakpoints.
  2. Every time I added a new cover, the other covers moved and the container for the map got larger and larger. I corrected the position of the Map by using Transforms but I still have a bunch of space on the bottom and I’m pretty sure this isn’t the best or correct way.

Any help would be appreciated.

Cheers,

Shawn

If you want to get down and dirty with a custom component, you could use a real interactive map :

Example code as a starting point:

<link
  rel="stylesheet"
  href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
/>
<div id="book-map" style="height: 520px; border-radius: 16px; overflow: hidden;"></div>

<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script>
  // Example data inline; swap with fetch("/locations.json")
  const locations = [
	{
	  bookTitle: "Book One",
	  series: "Series A",
	  placeName: "Edinburgh, Scotland",
	  lat: 55.9533,
	  lng: -3.1883,
	  coverImage: "https://m.media-amazon.com/images/I/714QlTE9fzL._SY522_.jpg",
	  link: "https://example.com/book-one",
	  blurb: "A mystery set in the Old Town…"
	}
  ];

  const map = L.map("book-map", { scrollWheelZoom: false });

  L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
	attribution: '&copy; OpenStreetMap contributors'
  }).addTo(map);

  const bounds = [];
  locations.forEach((loc) => {
	const marker = L.marker([loc.lat, loc.lng]).addTo(map);

	const popupHtml = `
	  <div style="display:flex; gap:12px; max-width:320px;">
		<img src="${loc.coverImage}" alt="${loc.bookTitle} cover"
			 style="width:72px; height:auto; border-radius:8px; object-fit:cover;" />
		<div style="font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial;">
		  <div style="font-weight:700; margin-bottom:2px;">${loc.bookTitle}</div>
		  <div style="opacity:.75; font-size:13px; margin-bottom:6px;">${loc.placeName}</div>
		  <div style="font-size:13px; line-height:1.25; margin-bottom:8px;">${loc.blurb}</div>
		  <a href="${loc.link}" style="font-size:13px; font-weight:600;">View book →</a>
		</div>
	  </div>
	`;
	marker.bindPopup(popupHtml);

	bounds.push([loc.lat, loc.lng]);
  });

  if (bounds.length === 1) map.setView(bounds[0], 10);
  else map.fitBounds(bounds, { padding: [40, 40] });
</script>


2 Likes

Thanks Doobox. This looks great. However, my wife would prefer a more stylized approach. I will certainly keep your code for future projects.

Is there a way to put multiple images over an image and keep them ‘stuck’ to the relative position below?

This is what it looks like so far:

(I can’t seem to upload images. I assume I’m too new.)

Thanks!