0
votes

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/

2

2 Answers

1
votes

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>
0
votes

It's worth noting that this can also be achieved without JS. CSS gives us all we need to animate transitions on hover:

.stage {
  height: 200px;
  width: 200px;
  background-color: #1d2452;
  color: white;
  position: relative;
  display: inline-block;
}

.title,
.desc {
  display: block;
  position: absolute;
  left: 0;
  right: 0;
  margin: 0;
  padding: 0;
  top: 50%;
  text-align: center;
  transform: translate(0%, -50%);
}

.desc {
  opacity: 0;
}

.stage:hover .caption .title {
  opacity: 0;
  -webkit-transition: opacity 200ms cubic-bezier(.02, .01, .47, 1);
  -moz-transition: opacity 200ms cubic-bezier(.02, .01, .47, 1);
  -ms-transition: opacity 200ms cubic-bezier(.02, .01, .47, 1);
  -o-transition: opacity 200ms cubic-bezier(.02, .01, .47, 1);
}

.stage:hover .caption .desc {
  opacity: 1;
  -webkit-transition: opacity 100ms cubic-bezier(.02, .01, .47, 1) 200ms;
  -moz-transition: opacity 100ms cubic-bezier(.02, .01, .47, 1) 200ms;
  -ms-transition: opacity 100ms cubic-bezier(.02, .01, .47, 1) 200ms;
  -o-transition: opacity 100ms cubic-bezier(.02, .01, .47, 1) 200ms;
}
<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>