-1

I'm using JavaScript animations on a web page. Now I noticed that I get this error:

Uncaught DOMException: Animation.commitStyles: Target is not rendered

I couldn't find any information at all about this. What does it mean? It happens in Firefox 110 on Windows. The same error occurs in Chrome 111:

Uncaught DOMException: Failed to execute 'commitStyles' on 'Animation': Target element is not rendered.

The Code looks like this:

let keep = undefined;
let anim = this.first.animate(keyframes, {
    duration: duration,
    fill: keep !== false ? "forwards" : "none"
});
if (keep !== false) {
    anim.addEventListener("finish", () => {
        anim.commitStyles();
        anim.cancel();
    });
}
ygoe
  • 18,655
  • 23
  • 113
  • 210

1 Answers1

0

Target element is not rendered

You will see the browser api throw an Target element is not rendered exception when you attempt to commitStyles on an element that is not rendered in the DOM.

Most likely the element you're attempting to set commitStyles on has a CSS rule that makes the element not rendered.
IE display: none

You guard against the execption by checking if the element is rendered.
This answer goes into more detail on sensible ways to check if an element is rendered.

Example/simulation

In general you could check if the element is rendered right before calling commitStyles

const divElem1 = document.querySelector(".item");

const toggleClass = () => {
  divElem1.classList.toggle("display-none");
}

function isHidden(el) {
  return (el.offsetParent === null)
}

let isSafeguarding = true;
const toggleSafeguard = (e) => {
  isSafeguarding = !isSafeguarding
  e.target.textContent = `safeguard is: ${isSafeguarding?'ON':'OFF'}`

}


document.body.addEventListener("mousemove", (evt) => {
  const anim1 = divElem1.animate({
    transform: `translate(${evt.clientX}px, ${evt.clientY}px)`
  }, {
    duration: 500,
    fill: "forwards"
  });

  if (!isSafeguarding || !isHidden(divElem1)) {
    anim1.commitStyles();
  }
});
.item {
  padding: 50px;
  display: inline-block;
  border: 2px solid navy;
  background-color: azure;
  position:absolute;
}

.item.display-none {
  display: none;
}

body {
  background-color: PeachPuff;
  width: 100vw;
  height: 100vh;
}

button {
  margin: 6px;
}
<div class="item one">moves to pointer</div>
<div>
  <div>Hide the element and turn off the safeguard to see an error.</div>
  <button onClick="toggleClass()">toggle display:none</button>
  <button onClick="toggleSafeguard(event)">safeguard is: ON</button>
</div>

Closing notes:

commitStyles is relatively new. Adoption in mayor browsers started around 2020.
This might be why still little documentation is available from the community.
In a sense you're pionering the documentation for future google searches for this specific error .

If you fancy reading the chromium source you can see the exact place and condition for the error to be thrown.

If you fancy reading the spec, there's an entry specific to commit styles

Lars
  • 3,022
  • 1
  • 16
  • 28
  • Hm, so the styles cannot be committed to an invisible element. But why? I don't see any use in this limitation. What when the element becomes visible again? It will be missing the final animation styles then. The animation is long gone and the element will be in an undefined state. It should keep the final animation styles instead. Should I just forget `commitStyles()` and do that work myself? – ygoe Mar 14 '23 at 18:20
  • It's defined like that in the spec, the second bullet point: "If, after applying any pending style changes, target is not being rendered, throw an "InvalidStateError" DOMException and abort these steps.". There reasons for that are beyond me, if i have to guess, it's because it would become very hard to calculate properties that are related to the layout (widht/height etc), I've added a link the the spec in the closing notes. – Lars Mar 15 '23 at 09:34