@@ -114,7 +114,7 @@ export class RippleRenderer implements EventListenerObject {
114114 const radius = config . radius || distanceToFurthestCorner ( x , y , containerRect ) ;
115115 const offsetX = x - containerRect . left ;
116116 const offsetY = y - containerRect . top ;
117- const duration = animationConfig . enterDuration ;
117+ const enterDuration = animationConfig . enterDuration ;
118118
119119 const ripple = document . createElement ( 'div' ) ;
120120 ripple . classList . add ( 'mat-ripple-element' ) ;
@@ -130,20 +130,30 @@ export class RippleRenderer implements EventListenerObject {
130130 ripple . style . backgroundColor = config . color ;
131131 }
132132
133- ripple . style . transitionDuration = `${ duration } ms` ;
133+ ripple . style . transitionDuration = `${ enterDuration } ms` ;
134134
135135 this . _containerElement . appendChild ( ripple ) ;
136136
137137 // By default the browser does not recalculate the styles of dynamically created
138- // ripple elements. This is critical because then the `scale` would not animate properly.
139- enforceStyleRecalculation ( ripple ) ;
138+ // ripple elements. This is critical to ensure that the `scale` animates properly.
139+ // We enforce a style recalculation by calling `getComputedStyle` and *accessing* a property.
140+ // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
141+ const computedStyles = window . getComputedStyle ( ripple ) ;
142+ const transitionProperty = computedStyles . transitionProperty ;
140143
141- // We use a 3d transform here in order to avoid an issue in Safari where
142- // the ripples aren't clipped when inside the shadow DOM (see #24028).
143- ripple . style . transform = 'scale3d(1, 1, 1)' ;
144+ // Note: We detect whether animation is forcibly disabled through CSS by the use
145+ // of `transition: none`. This is technically unexpected since animations are
146+ // controlled through the animation config, but this exists for backwards compatibility
147+ const animationForciblyDisabledThroughCss = transitionProperty === 'none' ;
144148
145149 // Exposed reference to the ripple that will be returned.
146- const rippleRef = new RippleRef ( this , ripple , config ) ;
150+ const rippleRef = new RippleRef ( this , ripple , config , animationForciblyDisabledThroughCss ) ;
151+
152+ // Start the enter animation by setting the transform/scale to 100%. The animation will
153+ // execute as part of this statement because we forced a style recalculation before.
154+ // Note: We use a 3d transform here in order to avoid an issue in Safari where
155+ // the ripples aren't clipped when inside the shadow DOM (see #24028).
156+ ripple . style . transform = 'scale3d(1, 1, 1)' ;
147157
148158 rippleRef . state = RippleState . FADING_IN ;
149159
@@ -156,15 +166,15 @@ export class RippleRenderer implements EventListenerObject {
156166
157167 // Do not register the `transition` event listener if fade-in and fade-out duration
158168 // are set to zero. The events won't fire anyway and we can save resources here.
159- if ( duration || animationConfig . exitDuration ) {
169+ if ( ! animationForciblyDisabledThroughCss && ( enterDuration || animationConfig . exitDuration ) ) {
160170 this . _ngZone . runOutsideAngular ( ( ) => {
161171 ripple . addEventListener ( 'transitionend' , ( ) => this . _finishRippleTransition ( rippleRef ) ) ;
162172 } ) ;
163173 }
164174
165175 // In case there is no fade-in transition duration, we need to manually call the transition
166176 // end listener because `transitionend` doesn't fire if there is no transition.
167- if ( ! duration ) {
177+ if ( animationForciblyDisabledThroughCss || ! enterDuration ) {
168178 this . _finishRippleTransition ( rippleRef ) ;
169179 }
170180
@@ -200,7 +210,7 @@ export class RippleRenderer implements EventListenerObject {
200210
201211 // In case there is no fade-out transition duration, we need to manually call the
202212 // transition end listener because `transitionend` doesn't fire if there is no transition.
203- if ( ! animationConfig . exitDuration ) {
213+ if ( rippleRef . _animationForciblyDisabledThroughCss || ! animationConfig . exitDuration ) {
204214 this . _finishRippleTransition ( rippleRef ) ;
205215 }
206216 }
@@ -371,14 +381,6 @@ export class RippleRenderer implements EventListenerObject {
371381 }
372382}
373383
374- /** Enforces a style recalculation of a DOM element by computing its styles. */
375- function enforceStyleRecalculation ( element : HTMLElement ) {
376- // Enforce a style recalculation by calling `getComputedStyle` and accessing any property.
377- // Calling `getPropertyValue` is important to let optimizers know that this is not a noop.
378- // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
379- window . getComputedStyle ( element ) . getPropertyValue ( 'opacity' ) ;
380- }
381-
382384/**
383385 * Returns the distance from the point (x, y) to the furthest corner of a rectangle.
384386 */
0 commit comments