Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to detect if an element has a CSS animation applied

I am attempting to fire an event on a web component when a CSS animation has completed, however there is a possibility the user might clear the animation from the element using animation: none; meaning the transitionend event never fires:

// wait for dialog close animation to end before firing closed event
element.addEventListener('transitionend', function() {

    // fire dialog closed event
    self.dispatchEvent(new CustomEvent('pure-dialog-closed', { 
        bubbles: true, 
        cancelable: true 
    }));
});

To ensure my custom event always fires, I need to determine if the element or any of its children have an animation applied and if not, fire the pure-dialog-closed event immediately.

I have tried checking style.animationName and self.style.transition but it does not appear to be working. I need a simple way of checking if an element, or any of its children have a CSS animation applied.

like image 837
John Doherty Avatar asked Jan 03 '23 10:01

John Doherty


2 Answers

You can use the getComputedStyle function. Following is an example which read the transition property of a div.

Read more about this here.
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

function getTheStyle() {
  var elem = document.getElementById("elem-container");
  var theCSSprop = window.getComputedStyle(elem, null).getPropertyValue("transition");
  document.getElementById("output").innerHTML = theCSSprop;
}

getTheStyle();
#elem-container {
  position: absolute;
  left: 100px;
  top: 200px;
  height: 100px;
  transition: all 1s;
}
<div id="elem-container"></div>
<div id="output"></div>
like image 55
Thusitha Avatar answered Jan 14 '23 12:01

Thusitha


Thank you @Thusitha. I used window.getComputedStyle along with animation-duration and transition-duration to determine if an animation existed as either would need to be greater than 0s for an animation/transition to play out.

The following inspects all elements including element passed in:

/**
 * Determine if an element of any or its children have a CSS animation applied
 * @param {HTMLElement} el - element to inspect
 * @returns {boolean} true if an animation/transition detected, otherwise false
 */
function hasCssAnimation(el) {

  // get a collection of all children including self
  var items = [el].concat(Array.prototype.slice.call(el.getElementsByTagName("*")));

  // go through each item in reverse (faster)
  for (var i = items.length; i--;) {

    // get the applied styles
    var style = window.getComputedStyle(items[i], null);

    // read the animation/transition duration - defaults to 0
    var animDuration = parseFloat(style.getPropertyValue('animation-duration') || '0');
    var transDuration = parseFloat(style.getPropertyValue('transition-duration') || '0');

    // if we have any duration greater than 0, an animation exists
    if (animDuration > 0 || transDuration > 0) {
      return true;
    }
  }

  return false;
}

var elementToTest = document.querySelector('.one');
var result = hasCssAnimation(elementToTest);

alert(result);
div {
  font-size: 14px;
  padding: 20px;
  color: #fff;
}

.one {
  background: red;
}

.two {
  background: green;
  animation: zoomIn 3s ease; /* <-- animation applied to child */
}

.three {
  background: blue;
}

@keyframes zoomIn {
  from {
    opacity: 0;
    transform: scale3d(.3, .3, .3);
  }
  50% {
    opacity: 1;
  }
}
<div class="one">
  <div class="two"> <!-- animation on child element -->
    <div class="three">
      Hello World
    </div>
  </div>
</div>
like image 41
John Doherty Avatar answered Jan 14 '23 14:01

John Doherty