Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@angular/animations] ViewEncapsulation.ShadowDom breaks Angular Animations #25672

Closed
nartc opened this issue Aug 25, 2018 · 21 comments
Closed
Assignees
Labels
area: animations freq3: high P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent type: bug/fix
Milestone

Comments

@nartc
Copy link
Contributor

nartc commented Aug 25, 2018

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

As title mentioned, setting ViewEncapsulation.ShadowDom will cause the Animations not being able to run at all. Use-case: I'm building an Angular Element in conjunction with Angular Animations to see if the two play well together.

Expected behavior

Setting ShadowDom Encapsulation strategy should work with Angular Animations.

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Angular version: 6.1.4


Browser:
- [x] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
 
For Tooling issues:
- Node version: 10.x  
- Platform:  Mac

Others:

@ngbot ngbot bot added this to the needsTriage milestone Sep 4, 2018
@robwormald robwormald added type: bug/fix severity3: broken area: core Issues related to the framework runtime labels Sep 5, 2018
@robwormald
Copy link
Contributor

triaged this with @matsko today, turns out this has never worked (!), even with the previous implementation of Shadow DOM. Definitely a bug.

@robwormald robwormald removed the area: core Issues related to the framework runtime label Sep 5, 2018
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Sep 27, 2018
@sandeepsuvit
Copy link

Any fixes for this?

@bjornharvold
Copy link

Yes, confirming. I have shadowdom on my web components and hammerjs specified in main.ts. Animations not working. If I remove shadowdom, animations work again.

@quekqh
Copy link

quekqh commented Jul 31, 2019

I was using primeng sidebar and there was a sliding animation to display the sidebar but the sliding animation to close the sidebar broke (cause I set my view encapsulation to shadow dom).

I restored the closing animation by inserting -webkit-transition: all 0.2s ease-in-out; I suspect webkit animations are somehow broken if view encapsulation shadow dom is added? Hope this helps someone!

@graypegg
Copy link

graypegg commented Aug 1, 2019

Can confirm we're seeing this as well, and our instance relies on a staggered animation so the work around is going to be messier than using the animations modules sadly :(

@ghost
Copy link

ghost commented Aug 3, 2019

This is still an issue; I was using the shadowdom when trying to use Angular Elements and then realized that this was breaking it:

  encapsulation: ViewEncapsulation.ShadowDom,

It took quite a while to track that down, at this point if there isn't a fix there should be a console log error or something because it is something that can be detected within the component declaration

if (encapsulation != emulated && animations.length > 0) {
  console.log('animations may not work properly');
}

@bjornharvold
Copy link

Any update on this?

@pigeonvictor
Copy link

pigeonvictor commented Aug 29, 2019

Same for me, animations not working on a encapsulation: ViewEncapsulation.ShadowDom,

@sinedoOo
Copy link

Same for my project. ShadowDom disables "transition" property. I've added manually in CSS transition filed and it's started working, but it's ugly and it's working only for very primitive animations. Any update for this issue?

@alexeykostevich
Copy link

alexeykostevich commented Sep 30, 2019

Our team faced the same issue while building encapsulated Web Components for a browser extension.

Please, let me share some our findings — probably, this could be helpful to get this tricky issue fixed one day.

Angular Animations uses different mechanisms depending on a browser:

  • Web Animations is used for browsers that support Web Animations API.
  • CSS Keyframes is used as a fallback for other browsers.

Web Animations

When Web Animations is used, the issue is caused by the WebAnimationsDriver module. The module does not take into account shadow DOM in the implementation of the containsElement method.

containsElement(elm1: any, elm2: any): boolean { return containsElement(elm1, elm2); }

As a result, Angular thinks that elements inside shadow DOM are not presented on a page (but just in memory) and skips animation.

const nodeIsOrphaned = !bodyNode || !this.driver.containsElement(bodyNode, element);

CSS Keyframes

When CSS Keyframes is used, Angular inherits the same issue as with Web Animations (through some shared modules).

In addition to this, Angular adds generated CSS with keyframes to the <head> but not inside shadow DOM. As a result, these styles are not visible for Web Component elements.

document.querySelector('head') !.appendChild(kfElm);

@Schibum
Copy link

Schibum commented Dec 2, 2019

@alexeykostevich thx. This monkey-patch fixes it for the web animations case:

import { ɵWebAnimationsDriver } from '@angular/animations/browser';
ɵWebAnimationsDriver.prototype.containsElement = (el1: any, el2: any) => {
  // Travel up the tree to the root node.
  let elem = el2;
  while (elem && elem !== document.documentElement) {
    if (elem === el1)
      return true;
    elem = elem.parentNode || elem.host;
  }
  return false;
};

@pianetarosso
Copy link

Somebody knows how to apply the same solution for CSS Keyframes?

@nrwinner
Copy link

Can confirm this is still an issue in Angular 9

@ray-kay
Copy link

ray-kay commented May 11, 2020

Angular Animations uses different mechanisms depending on a browser:

  • Web Animations is used for browsers that support Web Animations API.
  • CSS Keyframes is used as a fallback for other browsers.

Is there a way to force Angular to use Keyframes instead of Web Animations?

@OssprO
Copy link

OssprO commented Aug 14, 2020

Still an issue in Angular 10

@jelbourn jelbourn added P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent and removed severity3: broken labels Oct 1, 2020
@SmadusankaB
Copy link

Still an issue in Angular with the following versions.
"@angular/animations": "~10.0.2",
"@angular/cdk": "~10.1.3",
"@angular/common": "~10.0.2",
"@angular/compiler": "~10.0.2",
"@angular/core": "~10.0.2",

jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Dec 15, 2020
Closes angular#25672

Signed-off-by: jeripeierSBB <jeremias.peier@sbb.ch>
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Dec 16, 2020
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Dec 17, 2020
enhanced AnimationDriver's containsElement method to not only
use the native node contains-method but to walk up the DOM tree
by also considering shadow elements. Fixing this allows animations
to be played if they are placed inside a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Dec 17, 2020
enhanced AnimationDriver's containsElement method to not only
use the native node contains-method but to walk up the DOM tree
by also considering shadow elements. Fixing this allows animations
to be played if they are placed inside a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Dec 17, 2020
enhanced AnimationDriver's containsElement method to not only
use the native node contains-method but to walk up the DOM tree
by also considering shadow elements. Fixing this allows animations
to be played if they are placed inside a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Jan 19, 2021
enhanced AnimationDriver's containsElement method to not only
use the native node contains-method but to walk up the DOM tree
by also considering shadow elements. Fixing this allows animations
to be played if they are placed inside a shadow DOM.

Closes angular#25672
@fbcarpinato
Copy link

Still an issue on Angular 11

@JustDoItSascha
Copy link

Any updates on this?

@petebacondarwin
Copy link
Member

I'm afraid there is no update on fixing this at the moment. I am at full capacity with getting the new linker stuff ready - but I will take a look at the linked PR when I get a chance. Perhaps early next week.

@petebacondarwin petebacondarwin self-assigned this Mar 23, 2021
@jezmaghuyop
Copy link

just encountered the same issue on Angular 11, we are currently utilizing Angular elements which needed to be in a ShadowDom View Encapsulation. I've been trying to make a simple animation work for two days now only to find out that having our components in a ShadowDom is what breaking the animation.

this are my current versions

"@angular/animations": "^11.2.8", "@angular/cdk": "^11.2.3", "@angular/common": "~11.2.3", "@angular/compiler": "~11.2.3", "@angular/core": "~11.2.3", "@angular/elements": "^11.2.3",

jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 7, 2021
When determining whether to run an animation, the `TransiationAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 7, 2021
When determining whether to run an animation, the `TransiationAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 9, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 9, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 9, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 9, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 13, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 13, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 13, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 13, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
jeripeierSBB added a commit to jeripeierSBB/angular that referenced this issue Apr 13, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes angular#25672
AndrewKushnir pushed a commit that referenced this issue Apr 15, 2021
When determining whether to run an animation, the `TransitionAnimationPlayer`
checks to see if a DOM element is attached to the document. This is done by
checking to see if the element is "contained" by the document body node.

Previously, if the element was inside a shadow DOM, the engine would
determine that the element was not attached, even if the shadow DOM's
host was attached to the document. This commit updates the `containsElement()`
method on `AnimationDriver` implementations to also include shadow DOM
elements as being contained if their shadow host element is contained.

Further, when using CSS keyframes to trigger animations, the styling
was always added to the `head` element of the document, even for
animations on elements within a shadow DOM. This meant that those
elements never receive those styles and the animation would not run.
This commit updates the insertion of these styles so that they are added,
to the element's "root node", which is the nearest shadow DOM host, or the
`head` of the document if the element is not in a shadow DOM.

Closes #25672

PR Close #40134
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators May 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: animations freq3: high P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent type: bug/fix
Projects
None yet
Development

No branches or pull requests