google-maps-advanced-marker-collision-not-refresh
by wintlu
HTML
<div class="controls">
<h1>Advanced Marker Collision Bug Demo</h1>
</div>
<div id="map"></div>
<div class="toggle-container">
<button id="expandBtn">Change marker size</button>
<label class="toggle-switch">
<input type="checkbox" id="workaroundToggle" />
<span class="slider"></span>
</label>
<span id="statusLabel" class="status bug">Workaround OFF</span>
</div>
<div class="explanation">
<h2>The Bug</h2>
<p>
When an Advanced Marker has <code>collisionBehavior: REQUIRED_AND_HIDES_OPTIONAL</code>,
it should hide base map labels that fall within its bounds. However, when the marker's
content size changes dynamically (by adding/removing child elements), the collision bounds
are <strong>not recalculated</strong> — they remain based on the initial content size.
</p>
<h2>Steps to Reproduce</h2>
<ol>
<li>Create an Advanced Marker with <code>collisionBehavior: REQUIRED_AND_HIDES_OPTIONAL</code></li>
<li>Add a child element to the marker content (increasing its size)</li>
</ol>
<h2>Expected</h2>
<p>Base map labels underneath the expanded marker should be hidden.</p>
<h2>Actual</h2>
<p>Base map labels remain visible underneath the expanded marker because collision bounds are not recalculated.</p>
<h2>Try it</h2>
<ol>
<li>Click <strong>"Change marker size"</strong> — labels stay visible (bug)</li>
<li>Enable <strong>Workaround toggle</strong>, click button again — labels hide (fixed)</li>
</ol>
<h2>The Workaround</h2>
<p>
Slightly adjust the marker's position when the content size changes. This forces Google Maps
to recalculate the collision bounds based on the new content dimensions.
</p>
<pre><code>// When content expands, offset position slightly
const offset = isExpanded ? 0.00005 : 0;
marker.position = {
lat: originalPosition.lat + offset,
lng: originalPosition.lng
};</code></pre>
</div>
<script async
...
CSS
html, body {
height: 100%;
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
#map {
height: 400px;
width: 100%;
}
.controls {
padding: 12px;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.controls h1 {
margin: 0 0 4px 0;
font-size: 16px;
}
.controls p {
margin: 0 0 8px 0;
font-size: 13px;
color: #666;
}
.toggle-container {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
}
#expandBtn {
padding: 8px 16px;
font-size: 14px;
cursor: pointer;
background: #1a73e8;
color: white;
border: none;
border-radius: 4px;
}
#expandBtn:hover {
background: #1557b0;
}
.toggle-switch {
position: relative;
width: 44px;
height: 24px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
inset: 0;
background-color: #ccc;
transition: 0.3s;
border-radius: 24px;
}
.slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.3s;
border-radius: 50%;
}
input:checked + .slider {
background-color: #4CAF50;
}
input:checked + .slider:before {
transform: translateX(20px);
}
.status {
font-size: 12px;
padding: 3px 8px;
border-radius: 4px;
font-weight: 500;
}
.status.bug {
background: #ffebee;
color: #c62828;
}
.status.fix {
background: #e8f5e9;
color: #2e7d32;
}
/* Marker styles */
.marker {
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
padding: 8px;
text-align: center;
opacity: 0.5;
}
.marker .title {
font-weight: 600;
font-size: 14px;
color: #333;
}
.marker .details {
margin-top: 8px;
font-size: 12px;
color: #666;
line-height: 1.5;
}
.explanation {
padding: 16px;
...
JavaScript
/**
* Google Maps Advanced Marker Collision Bug Demo
*
* BUG: When marker content size changes (expand), the collision bounds
* don't update, so base map labels underneath are not hidden.
*
* WORKAROUND: Slightly adjust marker position to force collision recalculation.
*/
let map;
let marker;
let markerContent; // Reference to the content element
let isExpanded = false;
let useWorkaround = false;
// Position marker over an area with base map labels
const MARKER_POSITION = { lat: 37.7749, lng: -122.4194 }; // San Francisco
// Expose initMap globally for Google Maps callback
window.initMap = initMap;
async function initMap() {
const { Map } = await google.maps.importLibrary("maps");
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
// Create map centered on SF with zoom level that shows POI labels
// Vector map is required for collision behavior with base map labels
// Fractional zoom (17.5) only works on vector maps - if it rounds to 17 or 18, it's raster
map = new Map(document.getElementById("map"), {
center: MARKER_POSITION,
zoom: 17.5,
mapId: "4504f8b37365c3d0",
renderingType: google.maps.RenderingType.VECTOR,
});
// Check if vector map is being used
map.addListener("renderingtype_changed", () => {
console.log("Map rendering type:", map.getRenderingType());
});
// Log initial rendering type after map loads
map.addListener("tilesloaded", () => {
const renderingType = map.getRenderingType();
const actualZoom = map.getZoom();
console.log("Map loaded with rendering type:", renderingType);
console.log("Actual zoom level:", actualZoom, "(requested 17.5 - if rounded, it's raster)");
if (actualZoom !== 17.5) {
console.warn("WARNING: Zoom was rounded - NOT a vector map!");
}
});
// Create the marker
createMarker(AdvancedMarkerElement);
// Setup expand button
...