Search code examples
javascriptcssanimationhoverposition

Hover animation resetting( seemingly reverting back to original CSS and then again to hover)when moving mouse horizontaly accross a part of an element


I am trying to make a card animation where a card on the top of the deck would translate upwards when hovered. Unfortunately, it seems like my card flickers if I move my mouse horizontally over the bottom part of the card. I have made some tests and it seems to be related to the translate, as increasing the translate on hover will result in having a greater area accross the flickering happens. Sorry if I explained this bad, hopefully looking at the code will show what my issue is( simply mouse over the translated area after the translate has taken place and move your mouse vertically. You can also increase the translate to see the results).

I would be looking for any suggestions regarding this and/ or any advice regarding my code.

Thank you for your time and effort!

let game = document.getElementById('game');
let deckEl = document.getElementById('deck');
let hand = document.getElementById('hand');
// global variables
let arr = [{card: 1, text:"Attack"},{card: 2, text:"Attack"},{card: 3, text:"Attack"},{card: 4, text:"Shield"},{card: 5, text:"Shield"},{card: 6, text:"Shield"},{card: 7, text:"Parry"},{card: 8, text:"Parry"},{card: 9, text:"Parry"}];
let cardsInHand = [];
// shuffling the deck with selected deck as argument
function shuffleDeck(array) {
    let i = array.length;
    while(i--) {
        const i2 = Math.floor(Math.random()*i);
        [array[i], array[i2]] = [array[i2], array[i]];
    }
}
// drawing cards with card number as argument
function drawCards(cardAmount) {
    for(cardAmount; cardAmount > 0; cardAmount--) {
        cardsInHand.push(arr[arr.length-1]);
        arr.pop();
    }
}
// generate deck element
function generateDeck() {
    let cardOutline = 200;
    arr.forEach(card=> {
        let cardEl = document.createElement('div');
        cardEl.classList.add('card');
        cardOutline-=3;
        cardEl.style.top = cardOutline + "px"; 
        console.log(cardEl.style.top);
        deckEl.appendChild(cardEl);   
    })
}
generateDeck();     
shuffleDeck(arr);
drawCards(3);
#deck {
  display: flex;
  justify-content: space-around;
  position: relative;
}

.card {
  height: 100px;
  width: 100px;
  background-color: red;
  position: absolute;
  border: 1px solid black;
}

#deck .card:last-child {
  transition: transform 0.3s ease;
}

#deck .card:last-child:hover {
  transform: translateY(-20px);
}
<div class="container">
  <div id="game">
      <div id="deck"></div>
      <div id="hand"></div>
  </div>
</div>

I tried increasing modifying the translate and position properties, as well as the top and transitions, however it doesn't make much of a difference.

Here is the fiddle - https://jsfiddle.net/2hsg5bL4/


Solution

  • The 'shaky' hover problem arises because as the element moves up it is no longer hovered, so it comes back down and then it's hovered again and so on....

    This snippet moves the hover up one level so hovering on that causes the top card to move up but the hover remains on the parent.

    // grab elements
    let game = document.getElementById('game');
    let deckEl = document.getElementById('deck');
    let hand = document.getElementById('hand');
    // global variables
    let arr = [{
      card: 1,
      text: "Attack"
    }, {
      card: 2,
      text: "Attack"
    }, {
      card: 3,
      text: "Attack"
    }, {
      card: 4,
      text: "Shield"
    }, {
      card: 5,
      text: "Shield"
    }, {
      card: 6,
      text: "Shield"
    }, {
      card: 7,
      text: "Parry"
    }, {
      card: 8,
      text: "Parry"
    }, {
      card: 9,
      text: "Parry"
    }];
    let cardsInHand = [];
    // shuffling the deck with selected deck as argument
    function shuffleDeck(array) {
      let i = array.length;
      while (i--) {
        const i2 = Math.floor(Math.random() * i);
        [array[i], array[i2]] = [array[i2], array[i]];
      }
    }
    // drawing cards with card number as argument
    function drawCards(cardAmount) {
      for (cardAmount; cardAmount > 0; cardAmount--) {
        cardsInHand.push(arr[arr.length - 1]);
        arr.pop();
      }
    }
    // generate deck element
    function generateDeck() {
      let cardOutline = 200;
      arr.forEach(card => {
        let cardEl = document.createElement('div');
        cardEl.classList.add('card');
        cardOutline -= 3;
        cardEl.style.top = cardOutline + "px";
        //console.log(cardEl.style.top);
        deckEl.appendChild(cardEl);
      })
    }
    generateDeck();
    shuffleDeck(arr);
    drawCards(3);
    #deck {
      display: flex;
      justify-content: space-around;
      position: relative;
    }
    
    .card {
      height: 100px;
      width: 100px;
      background-color: red;
      position: absolute;
      border: 1px solid black;
    }
    
    #deck .card:last-child {
      transition: transform 0.3s ease;
    }
    
    #deck:hover .card:last-child {
      transform: translateY(-20px);
    }
    <link rel="stylesheet" href="style.css">
    <div class="container">
      <div id="game">
        <div id="deck"></div>
        <div id="hand"></div>
      </div>
    </div>