skip to Main Content

I am trying to make hover scale work smoothly with animation scale. Hover works with #test but with .rotate I can’t get it to work correctly. Also, why the hover scale doesn’t work when the animation-fill-mode is forwards instead of none?

https://codepen.io/yoholil/pen/qBLbYYm

let flag = false;
let test = document.querySelector("#test")


test.addEventListener("click", function() {
  console.log(1);
  flag && test.classList.add("rotate");
  !flag && test.classList.remove("rotate");
  flag = !flag;
});
#test {
  width: 200px;
  transition: 0.3s ease;
  animation: rotateRight 0.3s ease-in-out none;
}

#test:hover {
  transform: scale(1.2);
}

#test.rotate {
  transform: scaleX(-1);
  animation: rotateLeft 0.3s ease-in-out none;
}

@keyframes rotateRight {
  0% {
    transform: scaleX(-1);
  }
  100% {
    transform: scaleX(1);
  }
}

@keyframes rotateLeft {
  0% {
    transform: scaleX(1);
  }
  100% {
    transform: scaleX(-1);
  }
}
<img id="test" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Stack_Overflow_icon.svg/768px-Stack_Overflow_icon.svg.png" />

2

Answers


  1. If you need the initial flip animation, then consider using a CSS variable that carries the scaling multiplier so that it works within the animation:

    let flag = false;
    let test = document.querySelector("#test")
    
    
    test.addEventListener("click", function() {
      console.log(1);
      flag && test.classList.add("rotate");
      !flag && test.classList.remove("rotate");
      flag = !flag;
    });
    #test {
      transform: scale(var(--multiplier));
      width: 200px;
      transition: 0.3s ease;
      animation: rotateRight 0.3s ease-in-out none;
      --multiplier: 1;
    }
    
    #test:hover {
      --multiplier: 1.2;
    }
    
    #test.rotate {
      transform: scale(calc(-1 * var(--multiplier)), var(--multiplier));
      animation: rotateLeft 0.3s ease-in-out none;
    }
    
    @keyframes rotateRight {
      0% {
        transform: scale(calc(-1 * var(--multiplier)), var(--multiplier));
      }
      100% {
        transform: scale(var(--multiplier));
      }
    }
    
    @keyframes rotateLeft {
      0% {
        transform: scale(var(--multiplier));
      }
      100% {
        transform: scale(calc(-1 * var(--multiplier)), var(--multiplier));
      }
    }
    <img id="test" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Stack_Overflow_icon.svg/768px-Stack_Overflow_icon.svg.png" />

    Otherwise, if you don’t need the initial flip animation, consider removing the use of any animation altogether:

    let flag = false;
    let test = document.querySelector("#test")
    
    
    test.addEventListener("click", function() {
      console.log(1);
      flag && test.classList.add("rotate");
      !flag && test.classList.remove("rotate");
      flag = !flag;
    });
    #test {
      transform: scale(var(--multiplier));
      width: 200px;
      transition: 0.3s ease;
      --multiplier: 1;
    }
    
    #test:hover {
      --multiplier: 1.2;
    }
    
    #test.rotate {
      transform: scale(calc(-1 * var(--multiplier)), var(--multiplier));
    }
    <img id="test" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Stack_Overflow_icon.svg/768px-Stack_Overflow_icon.svg.png" />

    Additionally, the hover scale doesn’t work when the animation-fill-mode is forwards instead of none because the transform property value in the @keyframes would take precedence over any of properties defined in the CSS rules.

    Login or Signup to reply.
  2. Just use a wrapper and apply :hover to it:

    test.addEventListener('click', () => test.classList.toggle('rotate'));
    #test {
      width: 200px;
      transition: transform .3s ease;
    }
    
    #test:hover {
      transform: scale(1.2);
    }
    
    #test img{
      animation: rotateRight .3s ease-in-out both;
      max-width: 100%;
    }
    
    #test.rotate img{
      animation: rotateLeft .3s ease-in-out both;
    }
    
    @keyframes rotateRight {
      0% {
        transform: scaleX(-1);
      }
      100% {
        transform: scaleX(1);
      }
    }
    
    @keyframes rotateLeft {
      0% {
        transform: scaleX(1);
      }
      100% {
        transform: scaleX(-1);
      }
    }
    <div id="test">
      <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Stack_Overflow_icon.svg/768px-Stack_Overflow_icon.svg.png">
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search