Heyyy Marco
Heyyy Marco

Reputation: 753

CSS animation: hover-in and hover-out

I tried to make an animation that is triggered on hover and hover out. I didn't use the transition property because the animations are quite complex.

The hover-in works perfectly, but the hover-out always running at startup. It should animate when has been hover-in.

Then tried to set the CSS var --anim-hover-out: none, so no animation on startup. Then, on the end of hover-in, set --anim-hover-out: hover-out, so the hover-out animation now ready to play. But setting the CSS var inside @keyframes didn't work.

The goal is: .test:not(:hover):has-hover { do hover-out animation }

Note: no JavaScript, pure CSS only.

body {
  font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  padding: 100px;
  font-size: 13px;
}

div {
  background: #eee;
  margin: 0 auto;
  width: 200px;
  padding: 100px;
  text-align: center;
  /* border-radius */
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
  /* box-shadow */
  -webkit-box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
  -moz-box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
  box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
}
:root {
  --anim-hover-out: unset;
}

.test:not(:hover) {
  animation-name: var(--anim-hover-out);
  animation-duration: 500ms;
  animation-fill-mode: both;
}

.test:hover {
  animation-name: hover-in;
  animation-duration: 500ms;
  animation-fill-mode: both;
}
@keyframes hover-in {
  0: {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1.3);
    --anim-hover-out: hover-out;
  }
}
@keyframes hover-out {
  0: {
    transform: scale(1.3);
  }
  50% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1);
  }
}
<div class="test">Hello World!</div>

Upvotes: 5

Views: 7371

Answers (2)

Lajos Arpad
Lajos Arpad

Reputation: 76434

You can hide your content for the initial phases of page load via

body{
    animation-name: loading;
    animation-duration: 500ms;
    animation-fill-mode: both;
}

@keyframes loading {
  0% {
    opacity: 0;
  }
  99% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

which will hide your item while it's performing the hover-out animation at page initialization. If you want to avoid waiting, then you can attach the animations to classes, like .hovered and .blurred and toggle them via Javascript. If hiding body for one of its elements is too much, then you can wrap another div around your div and specify this animation for that one.

body {
  font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  padding: 100px;
  font-size: 13px;
}

div {
  background: #eee;
  margin: 0 auto;
  width: 200px;
  padding: 100px;
  text-align: center;
  /* border-radius */
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
  /* box-shadow */
  -webkit-box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
  -moz-box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
  box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
}
:root {
  --anim-hover-out: unset;
}

body{
    animation-name: loading;
    animation-duration: 500ms;
    animation-fill-mode: both;
}

@keyframes loading {
  0% {
    opacity: 0;
  }
  99% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

.test:not(:hover) {
  animation-name: hover-out;
  animation-duration: 500ms;
  animation-fill-mode: both;
}

.test:hover {
  animation-name: hover-in;
  animation-duration: 500ms;
  animation-fill-mode: both;
}
@keyframes hover-in {
  0: {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1.3);
    --anim-hover-out: hover-out;
  }
}
@keyframes hover-out {
  0: {
    transform: scale(1.3);
  }
  50% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1);
  }
}
<div class="test">Hello World!</div>

Upvotes: 0

BOZ
BOZ

Reputation: 2020

There is no way to set this without using JavaScript.

Because even if you manually define the animation name, the animation is triggered instantly.

  • So setting it up afterwards is not a solution. After the important (onmouseleave) thing you have to set it over.

See also snippet

A complete example that works

body {
  font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  padding: 100px;
  font-size: 13px;
}

div {
  background: #eee;
  margin: 0 auto;
  width: 200px;
  padding: 100px;
  text-align: center;
  /* border-radius */
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
  /* box-shadow */
  -webkit-box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
  -moz-box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
  box-shadow: rgba(0,0,0,0.2) 0px 1px 3px;
}
:root {
  --anim-hover-out: hover-out-fake;
}

.test:hover {
  animation-name: hover-in;
  animation-duration: 500ms;
  animation-fill-mode: both;
}

.test {
  animation-name: var(--anim-hover-out);
  animation-duration: 500ms;
  animation-fill-mode: both;
}

@keyframes hover-in {
  0: {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1.3);
    --anim-hover-out: hover-out;
  }
}
@keyframes hover-out {
  0: {
    transform: scale(1.3);
  }
  50% {
    transform: scale(0.8);
  }
  100% {
    transform: scale(1);
  }
}
<div class="test" onmouseleave="document.documentElement.style.setProperty('--anim-hover-out', 'hover-out')">Hello World!</div>

Upvotes: 3

Related Questions