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
 ...