Place Details Elements

The Place Details Element and Place Details Compact Element are HTML elements that render details for a place:

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 a lightbox-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. The light-scheme-color and dark-scheme-color attributes are used to set the color of the attribution text in light and dark mode.
See the 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.

See the 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>