The Place Details Element and Place Details Compact Element are HTML elements that render details for a place:
-
The
PlaceDetailsElement
supports all visualizable Place data, and may include multiple photos. -
The
PlaceDetailsCompactElement
is designed to consume minimal space and display a concise set of information about a place, including name, address, rating, etc. It may also include a single photo.
Place Details Element
The
PlaceDetailsElement
supports a broad range of content elements, including full opening hours, website, phone
number, editorial summary, type-specific highlights, reviews, plus code, and feature lists.
To display place details on a map, add a
gmp-place-details
element to the gmp-map
element on the HTML
page. Include a child element,
gmp-place-details-place-request
, to select the place. This can be a
Place object,
a
place ID,
or a Place's resource name in the format 'places/{place_id}':
<gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID"> <div class="widget-container" slot="control-inline-start-block-start"> <gmp-place-details> <gmp-place-details-place-request place="ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details> </div> <gmp-advanced-marker></gmp-advanced-marker> </gmp-map>
Configure the content
You can control the specific place content displayed by the
gmp-place-details
element using a nested
gmp-place-content-config
element to select and configure the place
details, as shown in this example:
<gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID"> <div class="widget-container" slot="control-inline-start-block-start"> <gmp-place-details> <gmp-place-details-place-request place="ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request> <gmp-place-content-config> <gmp-place-address></gmp-place-address> <gmp-place-rating></gmp-place-rating> <gmp-place-type></gmp-place-type> <gmp-place-price></gmp-place-price> <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon> <gmp-place-opening-hours></gmp-place-opening-hours> <gmp-place-website></gmp-place-website> <gmp-place-phone-number></gmp-place-phone-number> <gmp-place-summary></gmp-place-summary> <gmp-place-type-specific-highlights></gmp-place-type-specific-highlights> <gmp-place-reviews></gmp-place-reviews> <gmp-place-feature-list></gmp-place-feature-list> <gmp-place-media lightbox-preferred ></gmp-place-media> <gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution> </gmp-place-content-config> </gmp-place-details> </div> <gmp-advanced-marker></gmp-advanced-marker> </gmp-map>
The gmp-place-content-config
element itself contains a number of
child content elements, and each selects a corresponding place detail to display:
PlaceAddressElement
selects the place's address,
PlacePriceElement
selects the place's price level, etc. The order of child elements is irrelevant, as the
selected details are always rendered in a fixed predefined order.
Some of these elements can be further configured using content-specific attributes:
-
The
gmp-place-media
element is used to display a single photo, and includes alightbox-preferred
attribute that opens the photo in a lightbox when clicked. Lightbox is disabled by default. -
The
gmp-place-attribution
element is used to display the source of the photo. Thelight-scheme-color
anddark-scheme-color
attributes are used to set the color of the attribution text in light and dark mode.
PlaceContentConfigElement
reference documentation for more information about all supported content elements.
For simplicity, the
gmp-place-content-config
element can
be replaced with
gmp-place-all-content
to show all details available in the Place Details element, or with
gmp-place-standard-content
to display a standard configuration.
Configure the appearance
The recommended width range for the gmp-place-details
element is 250px-400px.
Widths less than 250px may not display correctly. Set the height to suit your application.
The Place Details element is designed to scroll within the allotted space as needed.
The gmp-place-details
element also supports a variety of custom CSS
properties to configure the element's colors and fonts. See
Places UI
Kit Custom Styling for more details.
See the complete code example
JavaScript
// Use querySelector to select elements for interaction. const map = document.querySelector('gmp-map'); const placeDetails = document.querySelector('gmp-place-details'); const placeDetailsRequest = document.querySelector('gmp-place-details-place-request'); const marker = document.querySelector('gmp-advanced-marker'); let center = { lat: 47.759737, lng: -122.250632 }; async function initMap() { // Request needed libraries. await google.maps.importLibrary("maps"); await google.maps.importLibrary("marker"); await google.maps.importLibrary("places"); // Hide the map type control. map.innerMap.setOptions({ mapTypeControl: false }); // Function to update map and marker based on place details const updateMapAndMarker = () => { if (placeDetails.place && placeDetails.place.location) { let adjustedCenter = offsetLatLngRight(placeDetails.place.location, -0.005); map.innerMap.panTo(adjustedCenter); map.innerMap.setZoom(16); // Set zoom after panning if needed marker.position = placeDetails.place.location; marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL; marker.style.display = 'block'; } }; // Set up map once widget is loaded. placeDetails.addEventListener('gmp-load', (event) => { updateMapAndMarker(); }); // Add an event listener to handle clicks. map.innerMap.addListener('click', async (event) => { marker.position = null; event.stop(); if (event.placeId) { // Fire when the user clicks a POI. placeDetailsRequest.place = event.placeId; updateMapAndMarker(); } else { // Fire when the user clicks the map (not on a POI). console.log('No place was selected.'); marker.style.display = 'none'; } }); } // Helper function to offset marker placement for better visual appearance. function offsetLatLngRight(latLng, longitudeOffset) { const newLng = latLng.lng() + longitudeOffset; return new google.maps.LatLng(latLng.lat(), newLng); } initMap();
CSS
/* * Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; font-family: Arial, Helvetica, sans-serif; display: block; } h1 { font-size: 16px; text-align: center; } gmp-map { height: 400px; } gmp-place-details { background-color: #fff; border-radius: 8px; margin: 20px; width: 400px; padding: 12px; margin-top: 10px; overflow-y: auto; } gmp-advanced-marker { display: none; } .widget-container { height: 400px; width: 457px; overflow-y: auto; overflow-x: hidden; }
HTML
<!DOCTYPE html> <html> <head> <title>Click on the map to view place details</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <gmp-map center="47.759737, -122.250632" zoom="16" map-id="DEMO_MAP_ID"> <div class="widget-container" slot="control-inline-start-block-start"> <gmp-place-details> <gmp-place-details-place-request place="ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details> </div> <gmp-advanced-marker></gmp-advanced-marker> </gmp-map> <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script> </body> </html>
Place Details Compact Element
The
PlaceDetailsCompactElement
renders details for a selected place using minimal space. This may be useful in an info window
highlighting a place on a map, in a social media experience like sharing a location in a chat,
as a suggestion for selecting your current location, or within a media article to reference
the place on Google Maps.The PlaceDetailsCompactElement
can display name,
address, rating, type, price, accessibility icon, open status, and a single photo.
To add the element to a map, add a
gmp-place-details-compact
element to the gmp-map
element on the HTML
page, and use the orientation
attribute to select whether it is displayed horizontally or vertically.
In the following example, gmp-place-details-compact
is nested within a
gmp-map
element, with orientation
set to horizontal
. An
additional attribute, truncation-preferred
, truncates certain content to fit on
one line instead of wrapping. The gmp-place-details-compact
element contains a child element,
gmp-place-details-place-request
, to select the place. This can be a
Place object,
a
place ID,
or a Place's resource name in the format 'places/{place_id}':
<gmp-map center="47.75972, -122.25094" zoom="19" map-id="DEMO_MAP_ID"> <gmp-place-details-compact orientation = "horizontal" truncation-preferred slot="control-block-start-inline-center" > <gmp-place-details-place-request place = "ChIJC8HakaIRkFQRiOgkgdHmqkk"></gmp-place-details-place-request> <gmp-place-content-config> <gmp-place-media lightbox-preferred></gmp-place-media> <gmp-place-rating></gmp-place-rating> <gmp-place-type></gmp-place-type> <gmp-place-price></gmp-place-price> <gmp-place-accessible-entrance-icon></gmp-place-accessible-entrance-icon> <gmp-place-open-now-status></gmp-place-open-now-status> <gmp-place-attribution light-scheme-color="gray" dark-scheme-color="white"></gmp-place-attribution> </gmp-place-content-config> </gmp-place-details-compact> <gmp-advanced-marker></gmp-advanced-marker> </gmp-map>
Configure the content
You can control the specific place content displayed by the
gmp-place-details-compact
element using a nested
gmp-place-content-config
element to select and configure the place
details. The gmp-place-content-config
element itself contains a number of
child content elements, and each selects a corresponding place detail to display.
The order of child elements is irrelevant, as the selected details are always rendered in a
fixed predefined order. Some of these elements can be further configured using
content-specific attributes.
PlaceContentConfigElement
reference documentation for more information about all supported content elements.
For simplicity, the
gmp-place-content-config
element can
be replaced with
gmp-place-all-content
to show all details available in the Place Details Compact element, or with
gmp-place-standard-content
to display a standard configuration.
Configure the appearance
The recommended width range for the gmp-place-details-compact
element in
vertical orientation is 180px-300px. Widths
less than 160px may not display correctly. Do not set a fixed height.
The recommended width range for the gmp-place-details-compact
element in
horizontal orientation is 180px-500px. Widths
less than 160px may not display correctly. At widths less than 350px, the thumbnail image
will not be shown. Do not set a fixed height.
The gmp-place-details-compact
element also supports a variety of custom CSS
properties to configure the element's colors and fonts. See
Places UI
Kit Custom Styling for more details.
See the complete code example
JavaScript
// Use querySelector to select elements for interaction. const mapContainer = document.getElementById("map-container"); const detailsContainer = document.getElementById("details-container"); const placeDetails = document.querySelector("gmp-place-details-compact"); const placeDetailsRequest = document.querySelector("gmp-place-details-place-request"); let gMap; let infowindow; let marker; async function initMap() { const { PlaceDetailsCompactElement, PlaceDetailsPlaceRequestElement } = await google.maps.importLibrary("places"); const { Map, InfoWindow } = await google.maps.importLibrary("maps"); const { AdvancedMarkerElement } = await google.maps.importLibrary("marker"); gMap = new Map(mapContainer, { mapId: 'DEMO_MAP_ID' }); marker = new AdvancedMarkerElement({ map: gMap }); infowindow = new InfoWindow({}); // Hide the map type control. gMap.setOptions({ mapTypeControl: false }); // Set up map, marker, and infowindow once widget is loaded. placeDetails.style.visibility = 'visible'; placeDetails.addEventListener('gmp-load', (event) => { console.log("placeDetails initialized!"); updateMapAndMarker(); }); // Add an event listener to handle clicks. gMap.addListener("click", async (event) => { marker.position = null; event.stop(); // Fire when the user clicks on a POI. if (event.placeId) { console.log("clicked on POI"); console.log(event.placeId); placeDetailsRequest.place = event.placeId; updateMapAndMarker(); } else { // Fire when the user clicks the map (not on a POI). console.log('No place was selected.'); } ; }); // Function to update map, marker, and infowindow based on place details const updateMapAndMarker = () => { console.log("function called"); if (placeDetails.place && placeDetails.place.location) { gMap.panTo(placeDetails.place.location); gMap.setZoom(16); // Set zoom after panning if needed marker.position = placeDetails.place.location; marker.collisionBehavior = google.maps.CollisionBehavior.REQUIRED_AND_HIDES_OPTIONAL; marker.style.display = 'block'; //@ts-ignore infowindow.setOptions({ content: placeDetails }); //@ts-ignore infowindow.open({ anchor: marker, map: gMap, }); } }; } initMap();
CSS
html, body { display: flex; width: 100%; height: 100%; margin: 0; } h1 { font-size: 16px; text-align: center; } #map-container { box-sizing: border-box; width: 100%; } gmp-place-details-compact { /* Sets the color for text and icons on the surface */ /* Adapts automatically to the user's system light/dark mode preference */ --gmp-mat-color-on-surface: light-dark(black, white); /* Sets the background color of the surface */ /* Adapts automatically to the user's system light/dark mode preference */ --gmp-mat-color-surface: light-dark(white, black); /* Defines the primary font stack used within the component */ --gmp-mat-font-family: Google Sans Text, sans-serif; /* Defines the style for medium body text (e.g., address, descriptions) */ --gmp-mat-font-body-medium: normal 400 0.875em/1.25em var(--gmp-mat-font-family, 'Google Sans Text'); width: 360px; border: none; overflow-y: hidden; } .gm-style-iw button { display: none !important; } .gm-style-iw-c { padding: 0 !important; margin: 0 !important; } .gm-style-iw-d { padding: 0 !important; margin: 0 !important; /* Sometimes margin can also contribute to unwanted space */ overflow: visible !important; /* If you don't want scrollbars, but be careful with content overflow */ } .gm-style-iw-c * { /* Target all elements inside the infowindow content container */ padding: 0 !important; margin: 0 !important; } @media (prefers-color-scheme: dark) { .gm-style-iw.gm-style-iw-c, .gm-style .gm-style-iw-d, .gm-style .gm-style-iw-d::-webkit-scrollbar-track, .gm-style .gm-style-iw-d::-webkit-scrollbar-track-piece, .gm-style .gm-style-iw-c, .gm-style .gm-style-iw-t::after, .gm-style .gm-style-iw-tc::after { background-color: #000 !important; } .gm-ui-hover-effect>span { background-color: #fff !important; } }
HTML
<!DOCTYPE html> <html> <head> <title>Click on the map to view place details</title> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script type="module" src="./index.js"></script> </head> <body> <div id = "map-container"> <gmp-place-details-compact orientation="horizontal"> <gmp-place-details-place-request place = ChIJn97JQNpC1moRIcJsVMEQLI8></gmp-place-details-place-request> <gmp-place-all-content></gmp-place-all-content> </gmp-place-details-compact> </div> <script> (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({ key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly" }); </script> </body> </html>