diff --git src/wp-admin/js/customize-widgets.js src/wp-admin/js/customize-widgets.js
index ea032c8469..d9b25115a9 100644
--- src/wp-admin/js/customize-widgets.js
+++ src/wp-admin/js/customize-widgets.js
@@ -1402,6 +1402,7 @@
 					self.container.addClass( 'expanded' );
 					$toggleBtn.attr( 'aria-expanded', 'true' );
 					self.container.trigger( 'expanded' );
+					$widget.addClass( 'open' );
 				};
 				if ( args.completeCallback ) {
 					prevComplete = complete;
@@ -1435,6 +1436,7 @@
 					self.container.removeClass( 'expanded' );
 					$toggleBtn.attr( 'aria-expanded', 'false' );
 					self.container.trigger( 'collapsed' );
+					$widget.removeClass( 'open' );
 				};
 				if ( args.completeCallback ) {
 					prevComplete = complete;
diff --git src/wp-admin/js/widgets/media-widgets.js src/wp-admin/js/widgets/media-widgets.js
index 452a9e38eb..45c0889654 100644
--- src/wp-admin/js/widgets/media-widgets.js
+++ src/wp-admin/js/widgets/media-widgets.js
@@ -1030,7 +1030,7 @@ wp.mediaWidgets = ( function( $ ) {
 	 * @returns {void}
 	 */
 	component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
-		var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, widgetInside, animatedCheckDelay = 50, renderWhenAnimationDone;
+		var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone;
 		widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
 		idBase = widgetForm.find( '> .id_base' ).val();
 		widgetId = widgetForm.find( '> .widget-id' ).val();
@@ -1088,9 +1088,8 @@ wp.mediaWidgets = ( function( $ ) {
 		 * This ensures that the container's dimensions are fixed so that ME.js
 		 * can initialize with the proper dimensions.
 		 */
-		widgetInside = widgetContainer.parent();
 		renderWhenAnimationDone = function() {
-			if ( widgetInside.is( ':animated' ) ) {
+			if ( ! widgetContainer.hasClass( 'open' ) ) {
 				setTimeout( renderWhenAnimationDone, animatedCheckDelay );
 			} else {
 				widgetControl.render();
diff --git src/wp-admin/js/widgets/text-widgets.js src/wp-admin/js/widgets/text-widgets.js
index bb19f2ffb2..3902aeddc0 100644
--- src/wp-admin/js/widgets/text-widgets.js
+++ src/wp-admin/js/widgets/text-widgets.js
@@ -354,7 +354,7 @@ wp.textWidgets = ( function( $ ) {
 	 * @returns {void}
 	 */
 	component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
-		var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, widgetInside, renderWhenAnimationDone, fieldContainer, syncContainer;
+		var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer;
 		widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
 
 		idBase = widgetForm.find( '> .id_base' ).val();
@@ -401,9 +401,8 @@ wp.textWidgets = ( function( $ ) {
 		 * This ensures that the textarea is visible and an iframe can be embedded
 		 * with TinyMCE being able to set contenteditable on it.
 		 */
-		widgetInside = widgetContainer.parent();
 		renderWhenAnimationDone = function() {
-			if ( widgetInside.is( ':animated' ) ) {
+			if ( ! widgetContainer.hasClass( 'open' ) ) {
 				setTimeout( renderWhenAnimationDone, animatedCheckDelay );
 			} else {
 				widgetControl.initializeEditor();
