Home > Software engineering >  My UI animation is sloppy using javascript to add and remove animation classes—is there a better way
My UI animation is sloppy using javascript to add and remove animation classes—is there a better way

Time:11-06

I'm trying to make this news item component interface for a blog. Each item shows a story image and some of the text of the article. Rolling over the news item should "scrunch up" the image and reveal more of the text of the article. I can't see why my animation does not hold when you rollover the item, and then it resets completely before performing the "unscrunching."

There are keyframe animations that attach and detach to the item:

@keyframes scrunch {
  from {
    height: 50%;
  }

  to {
    height: 10%;
  }
}

@keyframes unscrunch {
  from {
    height: 10%;
  }

  to {
    height: 50%;
  }
}

.scrunch {
  animation: scrunch 1s;
}

.unscrunch {
  animation: unscrunch 1s;
}

Then I'm just adding and removing those classes from the news item class list:

const scrunchyBox = document.getElementById('scrunchyBox1');
const children = scrunchyBox.childNodes;
console.dir(children);
const scrunchyBoxHead = children[1];

scrunchyBox.addEventListener('pointerover', (event) => {
  scrunchyBoxHead.classList.remove('unscrunch');
  scrunchyBoxHead.classList.add('scrunch');
});

scrunchyBox.addEventListener('pointerout', (event) => {
  scrunchyBoxHead.classList.remove('scrunch'); 
  scrunchyBoxHead.classList.add('unscrunch');
});

Seems basic, but whatever I'm doing looks gross. Everything I've done is over at my Codepen.

CodePudding user response:

  1. You can retain the animation in its final state using animation-fill-mode: forwards; as described in answer to this question: Maintaining the final state at end of a CSS3 animation

  2. It will still look janky if you remove pointer from the box mid-animation. I am not sure why you don't want to simply use CSS :hover with transition.

CodePudding user response:

You can use the transition property with the :hover pseudo-class. This will be the same that you have tryed to do with javascript.

To achieve this, just add few lines to your css file.

/* new block */
.scrunchyBox:hover .sectionHead {
  height: 10%;
}

.scrunchyBox > .sectionHead {
  width: 400px;
  height: 250px;
  background-color: #3ab7f4;
  padding: 0;
  margin: 0 auto;
  transition: all 0.5s ease-in-out; /* new line */
}

Show code snippet

body {
  background-color: #ccc;
  font-size: 18px;
}

.scrunchyBox {
  color: #333;
  position: relative;
  background-color: #fff;
  width: 400px;
  height: 400px;
  margin: 0 auto;
  padding: 20px;
  overflow: hidden;
  filter: drop-shadow(4px 4px 4px #333);
}

/* new block */
.scrunchyBox:hover .sectionHead {
  height: 10%;
}

.scrunchyBox > .sectionHead {
  width: 400px;
  height: 250px;
  background-color: #3ab7f4;
  padding: 0;
  margin: 0 auto;
  transition: all 0.5s ease-in-out; /* new line */
}

.datedot {
  position: absolute;
  top: 30px;
  right: 30px;
  background-color: rgba(0, 0, 0, 0.3);
  padding: 12px;
  border-radius: 60px;
  width: 60px;
  height: 60px;
}

.datedot > span {
  font-family: 'Trebuchet MS', sans-serif;
  color: rgba(255, 255, 255, 1);
  text-align: center;
  display: block;
  margin: 0;
}

.datedot > span.day {
  font-size: 2.2em;
  font-weight: bold;
  line-height: 0.8em;
  padding: 0;
}

.datedot > span.month {
  font-size: 1.3em;
  font-weight: normal;
  text-transform: uppercase;
  padding: 0;
}

.scrunchyBox > h2 {
  font-family: 'Trebuchet MS', sans-serif;
  font-size: 1.2em;
  line-height: 1em;
  padding: 0;
}

.scrunchyBox > p {
  font-family: 'Georgia', serif;
  font-size: 1.4em;
}
<div id="scrunchyBox1" class="scrunchyBox">
  <div class="sectionHead">
    <div class="datedot">
      <span class="day">30</span>
      <span class="month">Oct</span>
    </div>
  </div>
  <h2>A Headline for the Scrunchy Box</h2>
  <p>
    This is some text that would normally be some text that the reader would want to see more of. It gets cut off here by other elements, but then other elements "scrunch" in order to reveal more of the text for a preview.
  </p>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related