<ScriptGoogleMapsOverlayView>
Renders arbitrary Vue slot content at a map lat/lng position. Unlike InfoWindow, you have full control over HTML structure and styling.
positiongoogle.maps.LatLngLiteralGeographic position for the overlay. Falls back to parent marker position if omitted.
anchorOverlayAnchor = 'bottom-center'Anchor point of the overlay relative to its position.
offset{ x: number, y: number }Pixel offset from the anchor position.
paneOverlayPane = 'floatPane'The map pane on which to render the overlay.
zIndexnumberCSS z-index for the overlay element.
blockMapInteractionboolean = trueWhether to block map click and gesture events from passing through the overlay.
panOnOpenboolean | number = truePan the map so the overlay is fully visible when opened, similar to InfoWindow behavior. Set to `true` for default 40px padding, or a number for custom padding.
hideWhenClusteredboolean = trueAutomatically hide the overlay when its parent marker joins a cluster (on zoom out). Only applies when nested inside a ScriptGoogleMapsMarkerClusterer.
v-model:openbooleanMarker Anchoring
When nested inside a ScriptGoogleMapsMarker, the overlay automatically inherits the marker's position. This makes it a fully customizable alternative to InfoWindow, the overlay follows the marker when dragged.
<template>
<ScriptGoogleMaps api-key="your-api-key">
<ScriptGoogleMapsMarker
:position="{ lat: -34.397, lng: 150.644 }"
:options="{ gmpDraggable: true }"
>
<ScriptGoogleMapsOverlayView
anchor="bottom-center"
:offset="{ x: 0, y: -50 }"
>
<div class="custom-tooltip">
Fully custom content, no InfoWindow constraints
</div>
</ScriptGoogleMapsOverlayView>
</ScriptGoogleMapsMarker>
</ScriptGoogleMaps>
</template>
Popup on Marker Click
Using v-model:open keeps the overlay mounted, toggling visibility via CSS. This avoids remount cost and preserves internal state.
<script setup lang="ts">
const open = ref(false)
</script>
<template>
<ScriptGoogleMaps api-key="your-api-key">
<ScriptGoogleMapsMarker
:position="{ lat: -34.397, lng: 150.644 }"
@click="open = !open"
>
<ScriptGoogleMapsOverlayView
v-model:open="open"
anchor="bottom-center"
:offset="{ x: 0, y: -50 }"
>
<div class="custom-popup">
<button @click.stop="open = false">
×
</button>
<p>Any Vue content here</p>
</div>
</ScriptGoogleMapsOverlayView>
</ScriptGoogleMapsMarker>
</ScriptGoogleMaps>
</template>
For simple cases where remounting is acceptable, v-if also works:
<ScriptGoogleMapsMarker
:position="{ lat: -34.397, lng: 150.644 }"
@click="open = true"
>
<ScriptGoogleMapsOverlayView v-if="open">
<MyPopup @close="open = false" />
</ScriptGoogleMapsOverlayView>
</ScriptGoogleMapsMarker>
Persistent Label
<template>
<ScriptGoogleMaps api-key="your-api-key">
<ScriptGoogleMapsOverlayView
:position="{ lat: -34.397, lng: 150.644 }"
anchor="center"
:block-map-interaction="false"
>
<span class="bg-white px-1.5 py-0.5 rounded">
Label text
</span>
</ScriptGoogleMapsOverlayView>
</ScriptGoogleMaps>
</template>
Map Panning
When an overlay opens, the map automatically pans so the overlay is fully visible, matching the native InfoWindow behavior. The default padding is 40px from the map edge.
To customize the padding or disable panning:
<!-- Custom padding -->
<ScriptGoogleMapsOverlayView :pan-on-open="60">
...
</ScriptGoogleMapsOverlayView>
<!-- Disable panning -->
<ScriptGoogleMapsOverlayView :pan-on-open="false">
...
</ScriptGoogleMapsOverlayView>
Cluster Awareness
When used inside a ScriptGoogleMapsMarkerClusterer, overlay views automatically hide when their parent marker joins a cluster on zoom out. This prevents orphaned overlays from floating over cluster icons.
When its marker is clustered, the overlay updates v-model:open to false. The user will need to reopen the overlay (e.g. click the marker again) after zooming back in.
To disable this behavior:
<ScriptGoogleMapsMarkerClusterer>
<ScriptGoogleMapsMarker :position="markerPosition">
<ScriptGoogleMapsOverlayView :hide-when-clustered="false">
...
</ScriptGoogleMapsOverlayView>
</ScriptGoogleMapsMarker>
</ScriptGoogleMapsMarkerClusterer>
Transitions
The overlay sets a data-state attribute ("open" or "closed") on its content element, enabling CSS transitions and animations for enter/leave effects. When closing, the component waits for any running transitionend or animationend event before hiding the element.
Access the dataState via a template ref (it is exposed via defineExpose, not as a slot prop).
CSS Animation
The data-state attribute is automatically set on the overlay content element, so you can target it directly in CSS without needing to bind it manually.
<ScriptGoogleMapsOverlayView v-model:open="open">
<div class="popup">
Animated popup
</div>
</ScriptGoogleMapsOverlayView>
<style>
.popup[data-state="open"] {
animation: fadeIn 200ms ease-out;
}
.popup[data-state="closed"] {
animation: fadeOut 150ms ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes fadeOut {
from { opacity: 1; transform: scale(1); }
to { opacity: 0; transform: scale(0.95); }
}
</style>
CSS Transition
<script setup lang="ts">
const overlayRef = ref()
</script>
<template>
<ScriptGoogleMapsOverlayView ref="overlayRef" v-model:open="open">
<div
class="popup"
:style="{
opacity: overlayRef?.dataState === 'open' ? 1 : 0,
transition: 'opacity 200ms ease',
}"
>
Fade transition
</div>
</ScriptGoogleMapsOverlayView>
</template>
blockMapInteraction prop (default true) calls google.maps.OverlayView.preventMapHitsAndGesturesFrom() to stop clicks, taps, and drags from propagating through the overlay to the map. Set it to false for non-interactive overlays like labels.<ScriptGoogleMapsHeatmapLayer>
Heatmap visualization layer. Place inside a <ScriptGoogleMaps> component. The component automatically loads the visualization library.
useScriptGoogleMaps()
The useScriptGoogleMaps() composable lets you have fine-grained control over the Google Maps SDK. It provides a way to load the Google Maps SDK and interact with it programmatically.