Mozilla

Click highlights with CSS transitions

When you watch screencasts from time to time you’ll see that some software adds growing dots to the clicks the person explaining does to make them more obvious. Using CSS transitions this can be done very simply in JavaScript, too.
click highlighting with CSS

Check out the following demo on JSFiddle and you see what we mean. When you click on the document a dot grows where you clicked and it vanishes again. If you keep the mouse pressed the dot stays and you can move it around.

JSFiddle demo.

Moving the dot

The code is incredibly simple. We generate a DIV element and move it with the mouse. For this, we need JavaScript. Check the comments to see what is going on:

(function(){
 
  // create a DIV element, give it an ID and add it
  // to the body
  var plot = document.createElement('div'),
      pressed = false;
  plot.id = 'clickhighlightplot';
  document.body.appendChild(plot);
 
  // define offset as half the width of the DIV 
  // (this is needed to put the mouse cursor in
  // its centre)
  var offset = plot.offsetWidth / 2;
 
  // when the mouse is moved and the mouse button is pressed, 
  // move the DIV to the current position of the mouse cursor
  document.addEventListener('mousemove', function(ev) {
    if (pressed) { moveplot(ev.pageX, ev.pageY); }
  }, false);
 
  // when the mouse button is pressed, add a class called 
  // 'down' to the body of the element and define pressed
  // as true. Then move the DIV to the current mouse 
  // position.
  document.addEventListener('mousedown', function(ev) {
    document.body.classList.add('down');
    pressed = true;
    moveplot(ev.pageX, ev.pageY);
  }, false);
 
  // when the mouse is released, remove the 'down' class 
  // from the body and set pressed to false
  document.addEventListener('mouseup', function(ev) {
    document.body.classList.remove('down');
    pressed = false;
  },  false);
 
  // move the DIV to x and y with the correct offset
  function moveplot(x, y) {
    plot.style.left = x - offset + 'px';
    plot.style.top = y - offset + 'px';
  }
})();

This takes care of creating and moving the DIV and also gives us classes on the body element to play with.

Growing the dot

The growing of the dot uses CSS transitions. We change the scale of the dot from 0,0 to 1,1 in a certain amount of time. Notice that we need to scale down rather than up as Webkit zooms scaled elements instead of leaving crisp outlines like Firefox does (the first iteration of this script scaled a 10×10 pixel dot upwards and looked horrible).

#clickhighlightplot {
  cursor: pointer;
  pointer-events: none;
  background: rgba(255, 255, 10, 0.7);
  width:100px;
  height: 100px;
  position: absolute;
  border-radius: 100px;
  -webkit-transition: -webkit-transform 1s;
     -moz-transition: -moz-transform 1s;
      -ms-transition: -ms-transform 1s;
       -o-transition: -o-transform 1s;
          transition: transform 1s;
   -webkit-transform: scale(0, 0);
      -moz-transform: scale(0, 0);
       -ms-transform: scale(0, 0);
        -o-transform: scale(0, 0);
           transform: scale(0, 0);
}
.down #clickhighlightplot {
  -webkit-transform: scale(1, 1);
     -moz-transform: scale(1, 1);
      -ms-transform: scale(1, 1);
       -o-transform: scale(1, 1);
          transform: scale(1, 1);
}

Fixing the “covered clickable elements” issue

The main annoyance with the way the script works now is that you cover elements with the growing dot making them effectively unclickable. That might not be what you want which is why we need to make sure the dot covers them but still allows for clicks to go through. The good news is that there is a thing called pointer events for that. This is supported in Firefox and Webkit but sadly enough not in IE and Opera.

Moving from JS and CSS to pure JS (but using CSS)

Now, whilst it is cool to be able to maintain all the look and feel in CSS, the issue is that we need to repeat all the vendor prefixes and we run into issues that browsers might not support what we want to do. That’s why sometimes it makes more sense to move the whole functionality into JavaScript as we have the chance to test support there and write less code.

Clickhighlight.js does all that. Instead of keeping the maintenance in the CSS (and requiring you to add all the vendor prefixes) you can now have the effect by simply adding the script and calling its init() method:

<script src="clickhighlight.js"></script>
<script>clickhighlight.init();</script>

Elements with the class “nohighlight” will not get the effect. You can change the look by passing an initialisation object:

clickhighlight.init({
  size:        '300px', // the maximum size of the dot
  duration:    '2s',    // duration of the effect (seconds) 
  colour:      'green', // the dot colour - RGBA = transparency 
  nohighlight: 'notme'  // class of elements not highlighted
});

You can see it in action in this video on YouTube:

The next steps could be to add touch support and to turn this into a bookmarklet so you can use it on any page. Any other ideas?

7 comments

Comments are now closed.

  1. Shekhar wrote on April 23rd, 2012 at 04:09:

    Nice topic to cover. But I m not able to select the texts.. every time it enables bubble. I guess its good for demo only :(

    1. Chris Heilmann wrote on April 23rd, 2012 at 07:58:

      Can you tell me when you’d want to show a click in a screencast and then select text? I am at a loss to find a need for that…

      1. Shekhar wrote on April 23rd, 2012 at 21:55:

        This solution is perfect for showing clicks. The case is, I wanted to select words (definitely, I would want to show highlighted texts by selecting it in my screen cast.), but unable as any click creates the bubble.

  2. Ray. H wrote on April 23rd, 2012 at 06:57:

    Very cool, loving it.
    Thanks.

  3. dan (blogger) wrote on April 23rd, 2012 at 08:22:

    You could also change the shape of the highlight with this kind of plugin as well, or make it an image instead of just a color (preferably with very low opacity). Perhaps a different highlight for different parts of the page…

    I didn’t try it or anything yet but certainly this technique is food for thought…

  4. Ken Saunders wrote on April 23rd, 2012 at 08:28:

    I experienced something different than Shekhar when using the demo above. I suppose that the text isn’t supposed to be selected for the purpose of the demo anyway (screencasts, etc).

    When I clicked and moved the mouse around, blocks of text were highlighted (following typical click and drag behavior over text) along with the dot being displayed.
    When I used the middle mouse button, I was able to move the dot around without text being highlighted (as expected), but the middle mouse button isn’t always available for everyone and certainly not for touch devices.

    Also, the page would occasionally freeze (with Firefox).

    It’s still a very cool concept and I’m thinking that it could somehow be used like a handheld magnifying glass (thinking Virtual Magnifier type apps), for changing the foreground/background colors, or other accessibility related ideas.

    Thanks.

  5. Brother Fred wrote on April 30th, 2012 at 05:43:

    Click then then move the cursor then shift-click works to highlight the text.

Comments are closed for this article.