How to fully customize your Google Map Info Windows with Infobox

So I had a recent task of designing an infowindow for a Google map. Just in case you do not know, Google maps API has the ability of overlaying some HTML on top of a marker, also known as an “infowindow“.

The problem is, the default infowindow has limited options for HTML styling.

View Demo

The default infowindow looks like below:

regular

You can only style the inside of the window. We need a bit more flexibility and style the entire window.

Thankfully there’s this plugin called “Infobox“. With InfoBox, you can style the entire window by simply passing a few parameters. In my case, I need to make the window look like below:

modified2

Ready to get started? Let’s start by adding our script to InfoBox. Note that if you’re loading Google Maps asynchronously, you need to add your script in your callback method.

var initMap = function() {
  var s = document.createElement("script");
  s.type = "text/javascript";
  s.src = "js/infobox.js";
  $("head").append(s);
  var map = new google.maps.Map(document.getElementById('map-wrap'), {
    center: {lat: 33.78444500, lng: -118.15378000},
    zoom: 8
  });
}

Once your scripts are loaded, you should see your map, and add a simple marker like so:

var marker, i;
marker = new google.maps.Marker({
   position: new google.maps.LatLng(22.556444, -44.565),
   map: map
})

Now, InfoBox has plenty of options – so I just leave the defaults alone. What we really need is the “boxStyle” object. This we can pass our CSS as key/value pairs. This is the style of the outermost box – the box that the default infowindow doesn’t let you customize easily.

On a side note, I've really enjoyed the videos from Laracasts.com. These are high quality web developer tutorials on topics and technologies ranging from Laravel, React, Vue and many more. Head over to Laracasts and check them out!
var ibOptions = {
    		disableAutoPan: false
    		,maxWidth: 0
    		,pixelOffset: new google.maps.Size(-140, 0)
    		,zIndex: null
    		,boxStyle: {
          padding: "0px 0px 0px 0px",
          width: "252px",
          height: "40px"
        },
        closeBoxURL : "",
        infoBoxClearance: new google.maps.Size(1, 1),
    		isHidden: false,
    		pane: "floatPane",
    		enableEventPropagation: false
    	};

Once that’s done, let’s create a click handler, so our InfoBox will pop out when our marker is clicked. The code below is an example of a closure. We’re only including the “non static” properties inside our closure, so you’ll notice that our “innerHTML” property is inside.

google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        var source   = $("#infobox-template").html();
        var template = Handlebars.compile(source);
        var boxText = document.createElement("div");
        boxText.style.cssText = "margin-top: 8px; background: #fff; padding: 0px;";
        boxText.innerHTML = template(subSet[i]);
        ibOptions.content = boxText
        var ib = new InfoBox(ibOptions);
      	ib.open(map, marker);
        map.panTo(ib.getPosition());
      }
  })

I am also using Handlebars for templating, so the template is compiled multiple times. Also inside click handler above, and only shows up when the marker is actually clicked. My template will look like below. Remember that I have multiple of these boxes.

<div class="info-box-wrap">
  <img src="{{img_src}}" />
  <div class="info-box-text-wrap">
  <h6 class="address">{{address}}, {{city}} {{zip}} {{state}}</h6>
  <p class="price">{{price}}</p>
</div>
<div class="action-btns"></div>
</div>

Finally, the styles. Remember, InfoBox has already done the outer shell styles. Now it’s up to us to style the inner part of our box. So simply hack away with your CSS chops:

.info-box-wrap {
  background:#fff;
  overflow: hidden;
  box-shadow: 5px 5px 0px rgba(0, 0, 0, 0.08);
}
.info-box-text-wrap {
  height:40px !important;
  width:120px;
  float:left;
  overflow: hidden;
}
.action-btns {
  float:left;
  width:70px;
  overflow: hidden;
  position: relative;
  top:12px;
  left: 6px;
}
.action-btns i {
  font-size: 18px;
  color: #78A737;
  margin-left: 3px;
}
.action-btns i:hover {
  transition: color 0.5s ease;
  color:#ccc;
  cursor: pointer;
}
.action-btns i.fa-heart-o {
  font-weight: bold;
}
.info-box-text-wrap h6.address {
  padding:6px 5px 1px 0;
  margin:0 0 0 0;
  font-family:"Roboto Slab";
  color: #0c99c8;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.info-box-text-wrap p {
  padding:0 0 0 0;
  margin:0 0 0 0;
}
.info-box-text-wrap p.price {
  color:#B25B00;
}
.info-box-wrap  img {
  width:40px !important;
  height:40px;
  float:left;
  margin-right: 10px;
  padding-top:0;
  margin-top:0;
}

With the above code everything should be in place. All we need is an arrow that points back from our box to our marker.

Creating the Arrow

There is an awesome article on how to create traingles that is pure CSS. We really don’t need an image for this type of thing. Another thing, we’re going to use the ::before pseudo selector to insert our triangle. This prevents us from adding unnecessary DIVs into our markup.

.infoBox:before{
  content : " ";
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 10px solid #fff;
  position:absolute;
  top:-10px;
  left:130px;
}

Note the “content” property with the value of ” “. This makes it so the ::before selector is actually visible in the DOM.

And the final result looks like below. Note that the map automatically centers to the marker that is clicked. That is in our click handler “map.panTo(ib.getPosition())” method.

infobox2

Note that in the demo, it’s loading sample data from a text file. I’m also outputting which property is clicked on the left side.

Until next time, please leave your comments below.

affiliate link arrowdigitalocean banner

21 Comments

  1. Hey there,
    i can’t get it to work! I used the infoBox script form Github.
    I always get the error “InfoBox is not defined”. I’m loading the GoogleMaps API asynchronously, so i tried your solution for embedding the script, but it’s not working!
    I ended up trying to load both script like that:
    var script = document.createElement( ‘script’ );
    script.type = ‘text/javascript’;
    script.src = ‘https://maps.googleapis.com/maps/api/js?key=AIzaSyD3fp45yasXmwwbFt5KCh5T2GPvewfOqtg&callback=initMap’;
    document.getElementsByTagName(‘head’)[0].appendChild(script);
    script.onload = function () {
    var infoWindowScript = document.createElement( ‘script’ );
    infoWindowScript.type = ‘text/javascript’;
    infoWindowScript.src = “”;
    document.getElementsByTagName(‘head’)[0].appendChild(infoWindowScript);
    }
    but this does not work either.
    I’m calling
    var infoBox = new InfoBox(infoBoxOptions);
    by adding my markers in the initMap() function. Any idea, what the problem is?
    Thank you!

    Reply
  2. Hi Michael,
    We’ve gone through 3 designers trying to customize the infoWindows on our site. We’re not too technically savvy, but we do know that this job is achievable. We just keep believing that these programmers are telling us the truth – that they know how to do it – but they end up writing incomplete, fake, or disfunctional code. The language barriers don’t help, too.
    Currently the windows look ‘almost’ decent, but when in tablet or mobile view they fall apart. I’ve personally suggested using infoBubbles, or trying to use Marnoto’s custom infoWindow ideas, but no one can seem to implement these.
    This is the last piece of our website puzzle and we’d like to hire you to close the deal. After this task is complete, more work will be readily available. The site is an event discovery app.
    Please let me know if you can join our small team, at least on a temporary basis if not more.
    Thanks!
    charles

    Reply
  3. hi,
    I was struggling to have my infoboxes appearing under my differents markers.
    I changed
    ib.open(map, marker);
    to
    ib.open(map, this);
    and it helps me out
    Thanks again for having taken the time to write this out !
    wrong location wrong position problem location

    Reply
  4. I use Google ‘My Business’ and I’m wondering how to customize the hover text people see when seeing maps directly from Google maps site. I’ve noticed some businesses have managed to show multi-line text, for example, but I can’t figure out how to do this.

    Reply

Leave a Comment.