Posts Tagged ‘javascript’

Why is it flickering?

Sunday, January 31st, 2010

A friend of mine is learning JavaScript and jQuery and I recently helped her out with a problem she was having. She wanted to mouse over an image and have another <div/> appear, giving information about the image. Okay, nothing real strange there. But in her initial implementation she would mouse over the trigger image, the popup would appear, but then the popup would flicker, disappearing and reappearing repeatedly. I took what she started with and simplified it down to this to illustrate the problem:

<html>
  <head>
    <link rel="stylesheet" type="text/css" href="styles.css">
    <style type="text/css">
      #trigger {
        background-color: blue;
        display: block;
        height: 50px;
        width: 50px;
      }

      #popup {
        background-color: yellow;
        display: none;
        height: 200px;
        left: 25px;
        position: absolute;
        top: 25px;
        width: 100px;
      }
    </style>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
      $(document).ready(function(){
        $('#trigger').mouseover(function(){
          $('#popup').show('fast');
        });

        $('#trigger').mouseleave(function(){
          $('#popup').hide('fast');
        });
      });
    </script>
  </head>
  <body>
    <div id="trigger"></div>
    <div id="popup">Here is a bunch of text that will appear in the window
      that pops up. Lorem Ipsum and all that jazz.</div>
  </body>
</html>

If you view the page and point to the blue square, and yellow square with text pops up. Now move the mouse from the blue area to the yellow. As long as you’re in the overlap, the yellow area will repeatedly disappear and reappear.

What we wanted was that when you mouse over the blue, the popup would appear, and it would stay there until the mouse was over neither the blue trigger area nor the yellow popup. So that meant we needed to work with jQuery’s mouseleave event to hide the popup when leaving the target area. Here’s where it got tricky.

The area in red in the image to the left reflects the overlap of the two divs. Let’s think about what happens when we move the mouse from the blue trigger area to the red overlap. When the mouse crosses the line into the red, that triggers a mouseleave event from the trigger area. When that happens, we hide the popup. With the popup gone, the mouse is suddenly back in the blue div again. Mouseenter! That shows the popup again. Mouseleave! And so on.

So, what’s the solution? It was pretty straightforward in this case, once we understood what was happening. The real problem is that the trigger and popup divs are separate. In fact, the popup div should be a part of the trigger div, and then suddenly everything is easy. Why does that make a difference?

Take a look at the screenshot to the right. Here, the red area outlines the boundaries of the trigger div. Because the popup is now a child of the trigger, the mouse can roam around the yellow area without having left the trigger div, so we keep the popup showing.

The difference in the code is very simple; we just moved one div inside another, like so:

  <body>
    <div id="trigger">
      <div id="popup">Here is a bunch of text that will appear in the window
        that pops up. Lorem Ipsum and all that jazz.</div>
    </div>
 </body>

Of course, that led to some changes in the positioning of the popup, but that’s just a matter of working out new values for your CSS.

Moral of the story: when you want a popup, make it part of the trigger. That will let you have one region for the mouse to roam around in, making the event management nice and easy!