I just noticed that two of my Lightning Web Components' animations are colliding with each other.
Fragment of Component #1:
HTML:
<template>
<span class="my-element" if:true={showModal}/>
</template>
JS: showModal
is false
by default so this component is not displayed.
Listens for an event and sets the showModal
correspondingly.
CSS:
.my-element {
width: 25px;
animation: my-animation 0.75s;
}
@keyframes my-animation {
0% {
width: 0;
}
54% {
width: 0;
}
70% {
width: 50px;
}
84% {
width: 17px;
}
100% {
width: 25px;
}
}
Fragment of Component #2:
HTML:
<template>
<div class="loading-bar-wrapper-ds">
<div class="gr-my-image">
<img src={myImage} height="100" width="100"/>
</div>
<div class="col-my-img">
<img src={myImage} height="100" width="100"/>
</div>
</div>
</template>
JS: Sets the value of the my-image
variable.
CSS:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.loading-bar-wrapper-ds {
position: fixed;
z-index: 99999;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.gr-my-image {
filter: grayscale(100%);
position: relative;
}
.gr-my-image > img {
max-width: none;
}
.col-my-img {
position: absolute;
overflow: hidden;
top: 0;
left: 0;
width: 0;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-name: changeWidth;
animation-duration: 1s;
animation-timing-function: ease-in-out;
}
@keyframes changeWidth {
from {
width: 0;
}
to {
width: 100%;
}
}
.col-my-img > img {
max-width: none;
}
I find it bizarre that the animations collide even though:
- I am using web components so technically both components have their own shadow dom which should make the CSS code for each component invisible for the other.
- The
<span>
from Component #1 is not even in the DOM on load of the page yet its animation is breaking the animation of component #2. - The animations for both components have completely different names and still collide.
I thought I had found a solution to this but I guess not.
Has anybody else experienced such a problem and what would the explanation for this be?
EDIT
I separated this into a simple HTML file and noticed that the animations do not collide.
So then as a next step, following sfdxfox'es suggestion, I moved my 2 components to a playground and everything was working alright.
Then I went back to my LWC project, which btw is inside a community portal, and I noticed that the names for the animations are being overwritten! So for example if my css property was animation-name: changeWidth;
that would change to animation-name: a;
by the time it would load in the browser's inspector.
So then I looked at the animation names, in the inspector, for the other component(which has a bunch) and noticed that they were also overwritten following the same pattern a
,b
,c
.
So basically component #1 had a
,b
,c
,d
and component #2 had a
.
I also noticed that the @keyframes from component #1's animation somehow transferred into component #2 animation. I imagine that's related to both components having the same animation name of a
. But even if that's the case I thought this shouldn't be a problem because of the different shadow DOMs?
Here's a preview of what component #2 animation looks like in the inspector:
Needless to say the keyframes from the screenshot actually belong to component #1 but are assigned to component #2.
EDIT 2 I have now put a simplified example on this link: https://developer.salesforce.com/docs/component-library/tools/playground/d103Sw2J/2/edit
What you can witness is that animations with the same name are colliding with each other even though they are in separate components.
However if you are to try this in a Lightning Web Component the animations don't even need to have the same name and they will still be overwritten.
TLDR
I noticed that the CSS animation names for classes are being overwritten by Salesforce with single letters in alphabetical order starting with the letter a
. This would somehow collide between different components that would inevitably have the same animation names since all begin at a
. This leads to keyframes from one component being assigned to a completely different component.
changeWidth
, if you change it to something else in one of the two components the animation of the ball will resume. In my real LWC project both components are separate, they are not a parent-child duo.