John John - 1 month ago 15
CSS Question

Don't let the :after animation rule fire on page load

I have the following code that does almost everything I need it to do.



.mouse {
margin-bottom:20px;
padding:5px;
overflow:hidden;
width:200px;
}
.mouse:after {
content:"";
height:2px;
display:block;
background:red;
margin-top:5px;
transform:translateX(100%);
animation: hoverOut 1.5s ease 1;
}
.mouse:hover:after {
animation: hoverIn 1.5s ease 1;
}
@keyframes hoverOut {
0% {transform:translateX(0%);}
100% {transform:translateX(100%);}
}
@keyframes hoverIn {
0% {transform:translateX(-100%);}
100% {transform:translateX(0%);}
}

<div class="mouse">watch the line below</div>





Basically when you mouse over the text, you see a line slide in from the left. When you mouse out, you see the line slide out to the right.

My problem is if you go to your browser and press the refresh button to cause a page load, you'll see a line travel off to the right. I do not want this animation effect on page load. Is there something I can do with just HTML and CSS ? I do not want to introduce Javascript unless I absolutely have to.

Answer

Instead of using an animation use a transition with the property transform and a value of scaleX.

The "trick" here is to change transform-origin on the hover state.

Basically you do this:

.mouse:after {
  content: "";
  transform: scaleX(0);
  transition: transform 1.5s ease;
  transform-origin: right;
}
.mouse:hover:after {
  transform: scaleX(1);
  transform-origin: left;
}

Code Snippet:

.mouse {
  margin-bottom: 20px;
  padding: 5px;
  overflow: hidden;
  width: 200px;
}
.mouse:after {
  content: "";
  height: 2px;
  display: block;
  background: red;
  margin-top: 5px;
  transform: scaleX(0);
  transition: transform 1.5s ease;
  transform-origin: right;
}
.mouse:hover:after {
  transform: scaleX(1);
  transform-origin: left;
}
<div class="mouse">watch the line below</div>


If you however want to use your animation as it is, you would need to use javascript.

You need to add a class once the user hovers your element, in this case .running.

The basics are this:

.mouse:after {
  content: "";
  transform: translateX(100%);
  animation: hoverOut 1.5s ease 1;
  animation-play-state: paused; /* Initial state of the animation, paused. */
  animation-delay: -1.5s; /* Get the last frame of the animation, this value has to be the total duration of the animation with a negative value */
}
.mouse.running:after {
  animation-play-state: running; /* When the class is added, the animation state is changed to running */
  animation-delay: 0s /* Get the normal flow, starting from the first frame */;
}

Code Snippet:

document.querySelector(".mouse").addEventListener("mouseenter", function() {
  this.classList.add("running");
});
.mouse {
  margin-bottom: 20px;
  padding: 5px;
  overflow: hidden;
  width: 200px;
}
.mouse:after {
  content: "";
  height: 2px;
  display: block;
  background: red;
  margin-top: 5px;
  transform: translateX(100%);
  animation: hoverOut 1.5s ease 1;
  animation-play-state: paused;
  animation-delay: -1.5s;
}
.mouse.running:after {
  animation-play-state: running;
  animation-delay: 0s;
}
.mouse:hover:after {
  animation: hoverIn 1.5s ease 1;
}
@keyframes hoverOut {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(100%);
  }
}
@keyframes hoverIn {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(0%);
  }
}
<div class="mouse">watch the line below</div>


Comments