Search code examples
jqueryfadeinfadeoutmouseentermouseleave

mouseenter/mouseleave caption swap not working when moving mouse too quickly


I have a issue using mouseenter/mouseleave to trigger behaviour, where moving the most over the targeted elements too quickly causes undesirable behaviour. I've seen a few threads with similar problems, but none that seem to solve my issue.

I'm creating a grid of images with overlaid 'title' captions. I'm trying to make it so that when the user mouses over a image in the grid, the title caption fades out, and a 'description' caption is displayed in its place. This is then reversed on mouseleave and the title caption reappears.

I've used mouseenter / mouseleave and fadeIn / FadeOut to achieve the effect - it works ok when moving slowly between the blocks, but if moving too quickly, the 'title' and 'description' are both left displaying simultaneously. Here is my code:

$(".stage").mouseenter(function() {
  var desc = $(".desc", this);
  var title = $(".title", this);
  title.fadeOut(200, "swing", function() {
    desc.fadeIn(100, "swing");
  });
}).mouseleave(function() {
  var desc = $(".desc", this);
  var title = $(".title", this);
  desc.fadeOut(0, "swing", function() {
    title.fadeIn(0, "swing");
  });
});
.stage {
  height: 200px;
  width: 200px;
  background-color: #1d2452;
  color: white;
  position: relative;
  display: inline-block;
}

.stage > .caption {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-right: -50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

.desc {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stage">
  <div class="caption">
    <h2 class="title">Title</h2>
    <p class="desc">Description Text</p>
  </div>
</div>

<div class="stage">
  <div class="caption">
    <h2 class="title">Title</h2>
    <p class="desc">Description Text</p>
  </div>
</div>

<div class="stage">
  <div class="caption">
    <h2 class="title">Title</h2>
    <p class="desc">Description Text</p>
  </div>
</div>

And JSfiddle here - https://jsfiddle.net/y16nufd7/1/


Solution

  • Use stop() to achieve this:

    $(".stage").mouseenter(function() {
      var desc = $(".desc", this);
      var title = $(".title", this);
      title.stop().fadeOut(200, "swing", function() {
        desc.stop().fadeIn(100, "swing");
      });
    }).mouseleave(function() {
      var desc = $(".desc", this);
      var title = $(".title", this);
      desc.stop().fadeOut(0, "swing", function() {
        title.stop().fadeIn(0, "swing");
      });
    });
    .stage {
      height: 200px;
      width: 200px;
      background-color: #1d2452;
      color: white;
      position: relative;
      display: inline-block;
    }
    
    .stage > .caption {
      position: absolute;
      top: 50%;
      left: 50%;
      margin-right: -50%;
      transform: translate(-50%, -50%);
      text-align: center;
    }
    
    .desc {
      display: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="stage">
      <div class="caption">
        <h2 class="title">Title</h2>
        <p class="desc">Description Text</p>
      </div>
    </div>
    
    <div class="stage">
      <div class="caption">
        <h2 class="title">Title</h2>
        <p class="desc">Description Text</p>
      </div>
    </div>
    
    <div class="stage">
      <div class="caption">
        <h2 class="title">Title</h2>
        <p class="desc">Description Text</p>
      </div>
    </div>