Responsive point markers
HTML
<h1>Resize me!</h1>
<div id="map"></div>
CSS
html, body {
font-family: sans-serif;
}
/* Using background image here but you can also use a regular image. */
#map {
background-image: url("https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fstorage.googleapis.com%2Fpod_public%2F1300%2F159302.jpg&f=1&nofb=1&ipt=b4ba1c401d28ae03472d7afa0383f2fc3a07913880bbbce5b294d465fe6bb9ab&ipo=images");
width: 100%;
aspect-ratio: 3 / 2;
background-size: 100%;
position: relative; /* Important. This places points relative to the map.*/
}
.point {
display: flex;
align-items: center;
gap: 0.25rem;
margin-top: -0.75rem; /* Align to center of point */
margin-left: -0.75rem; /* Align to center of point */
position: absolute; /* Allows positioning via top and left properties */
}
.graphic {
border-radius: 50%;
background-color: deepskyblue;
width: 1.5rem;
height: 1.5rem;
}
.label {
background: rgba(0, 0, 0, 0.5);
color: white;
padding: 0.2rem;
}
JavaScript
/**
* List of points that you want to add.
* The x and y positions are supplied manually here,
* but you can calculate them by positioning them
* in your design software and calculate as follows,
* assuming the origin is at the top left corner of the map.
*
* x = (pointAbsoluteX - mapAbsoluteX) / mapWidth
* y = (pointAbsoluteY - mapAbsoluteY) / mapHeight
*/
const points = [
{ name: "France", x: 0.5, y: 0.365},
{ name: "Brazil", x: 0.37, y: 0.64}
]
let map;
window.addEventListener("DOMContentLoaded", () => {
map = document.getElementById("map");
for(const point of points) {
// Create the points.
const element = document.createElement("div");
const graphic = document.createElement("div");
const label = document.createElement("span");
element.className = "point";
graphic.className = "graphic";
label.className = "label";
label.innerHTML = point.name;
element.appendChild(graphic);
element.appendChild(label);
// We're not adding the position of the map because
// the browser will already place the points relative to the map
// thanks to the `position: absolute` and `relative` combination.
element.style.left = map.clientWidth * point.x + 'px';
element.style.top = map.clientHeight * point.y + 'px';
// Add them to the map
map.appendChild(element);
}
})
window.addEventListener("resize", () => {
// Assuming the list is constant.
// For points lists that can change, you might have to use keys
// to find the correct element to update.
for(let i=0;i<map.children.length;i++) {
const pointElement = map.children[i];
const pointData = points[i];
pointElement.style.left = map.clientWidth * pointData.x + 'px';
pointElement.style.top = map.clientHeight * pointData.y + 'px';
}
})