Creating Animated Google Map Markers with CSS and JavaScript

Kevin Kononenko
Animated Google Maps markers

Original image: DeviantArt

The Google Maps API allows web developers to create an excellent user experience with just a few lines of code through their magical, built-in functions.

However, there’s one glaring exception: flexibility and creativity with map markers.

Sure, you can add a custom marker image, a tooltip, and a label. But those are all static, text-oriented ways of interacting, which can become overwhelming on a map with many points. There’s no standard way to create interactive markers that respond to the user’s actions.

I simply wasn’t satisfied with this, so I set out to find a way to create truly distinctive maps. I’m going to show you how to include CSS3 animations on your map markers so that you can have them dance, wriggle and hide until they pretty much jump out of the screen.

If the user hovers over a marker, clicks on it or uses a toggle outside the map, you’ll be able to use any CSS animation to bring it to life. This guide will focus on a simple strategy you can use to include animated markers in any of your projects. (For comparison, two other examples — by Ryan Connolly and Felipe Figueroa — use a similar method.)

Here’s a basic example of animated markers at work. The famous Cheshire Cat acts as a marker for three separate points in Massachusetts, and you can use the toggle in the top right to change his animations:

See the Pen CSS Google Map Markers by SitePoint (@SitePoint) on CodePen.

The Basics

There a few steps you’ll need to take to add CSS animation capabilities to your markers.

Step 1

Add an image to your markers. This is how you specify your image:

var catIcon = {
    url: myImageURLhere,
    //state your size parameters in terms of pixels
    size: new google.maps.Size(70, 60),
    scaledSize: new google.maps.Size(70, 60),
    origin: new google.maps.Point(0,0)

Step 2

Add optimized:false to the marker specification. This allows you to render each marker as a separate DOM element:

var marker = new google.maps.Marker({
    map: map,
    // set the icon as catIcon declared above
    icon: catIcon,
    // must use optimized false for CSS
    optimized: false

Step 3

Create an overlayView that will organize all your markers in one pane, which you can then access from the DOM:

var myoverlay = new google.maps.OverlayView();
    myoverlay.draw = function () {

You can give your marker layer an id on the getPanes() line so you can use it in CSS. This Overlay view will automatically collect any markers that are not already in another layer. In this case, there are no other layers, so it collects all markers.

Step 4

Use CSS to give an animation to all markers in your layer. This can be an animation that happens once, or happens continuously:

#markerLayer img {
  animation: pulse .5s infinite alternate;
  -webkit-animation: pulse .5s infinite alternate;
  transform-origin: center;
  -webkit-transform-origin: center;

Flexibility Options

The above steps will let you add an animation to all markers immediately, so here are a few options for greater control over animating your markers.

External toggle

Let’s say you want to include a legend or some clickable toggles so that users can show and hide different layers, or have markers with certain features change their CSS animation. That’s easy! Just use a jQuery .click() handler, like this:

   $('#markerLayer img').css('animation', 'myAnimationOptionsHere');
   $('#markerLayer img').css('-webkit-animation', 'myAnimationOptionsHere')

On click/hover

Want to add a brief animation when users hover over one marker, or click on it? Let the hackiness begin! First, create a global array to store all your markers:

var allMarkers=[];

Then, when you declare each marker, add a title attribute and stringify it:

var marker = new google.maps.Marker({
    map: map,
    icon: catIcon,
    optimized: false,
    title: allMarkers.length.toString()

Adding a title attribute that is dependent on the length of the array will create unique ids for each marker. Then add the marker to the array:


Finally, here are your click and hover events. You identify each individual marker by using this individual title identifier:

google.maps.event.addListener(marker, 'click', function() {
  var thisTitle= Number(this.title);
  $('#markerLayer img').eq(thisTitle).css()...

google.maps.event.addListener(marker, 'mouseover/mouseout', function() {
  var thisTitle= Number(this.title);
  $('#markerLayer img').eq(thisTitle).css()...

Different animations for different marker types

Let’s say you add two separate marker types to a map: baseball fields and football fields. Since both are automatically included in your overlay layer, you need a way to apply separate animations to each of them. That’s easy! Just use the src attribute in your CSS and match it with the image URL of the respective markers:

#markerLayer img[src='/img/myURLpath'] {
    animation: pulse .5s infinite alternate;
    -webkit-animation: pulse .5s infinite alternate;
    transform-origin: center;
    -webkit-transform-origin: center;

Final Thoughts

Your main job as a developer or a designer is to build a product that your users love. They’ve seen plenty of Google Maps in the products that they already use. This is your opportunity to blow their expectations away!

Here are a couple ways map marker animations can create delight for your users:

  • If you have marker images that resemble actual things that move (like cats!), give them a CSS animation that corresponds to a natural movement.
  • If you have map marker images that don’t traditionally move (like a store), apply an animation that makes it seem like the images are happy you clicked them, like a jump or a shudder.
  • If you have data that corresponds to each marker, make the marker react based on the data. Let’s say you’re labeling intersections that are heavily trafficked: you can put a flashing exclamation point over those areas.

Try it out, and wait for the user compliments to roll in!

Did this guide help you? Let me know in the comments!