3

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: enter image description here enter image description here

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.

| improve this question | | | | |
  • 1
    Could you make a playground so we could play with the code without lots of effort just to set it up? – sfdcfox Aug 16 '19 at 19:49
  • I figured as much but I just didn't have the time at the writing of this post. I will try to set up something later! – Arthlete Aug 16 '19 at 20:34
  • @sfdcfox I added an edit. Please take a look and let me know your thoughts. Why would Salesforce overwrite the animation names? Are they trying to minimize the CSS? If so why are the CSS properties colliding if they are in different Shadow DOMs? I also noticed that the animation names do not get overwritten in the playground! – Arthlete Aug 16 '19 at 23:27
  • @sfdcfox I managed to replicate the same experience in the playground the moment I set the animation name to the same value inside both components. developer.salesforce.com/docs/component-library/tools/… The animation name is 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. – Arthlete Aug 16 '19 at 23:33
1

I opened a ticket with Salesforce and I got a response from their R&D team.

It seems like Salesforce are using CSS Loader to gather all of the css files and combine them into a string.

The bug I've witnessed is coming from there, not Salesforce per se. For that reason it doesn't appear that Salesforce will be addressing this. Instead they linked me to an article and a github discussion.

What I ended up doing(at first before contacting salesforce) is keep all of my animations in the same component so they don't overwrite each other. The downside to that is that things can get out of hand if you use CSS animations heavily.

Based on the article that Salesforce linked me I will instead Just copy the keyframe rules into each component’s CSS and live with minor redundancy. Again this redundancy depends on how many css animations you are using and can get out of hand. However at least that will allow you to get over some complications of storing complex animations in a single component. The key here will be to ensure that your keyframes are in the same order every time or else you might get the wrong animation assigned to your component.

| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.