diff --git src/wp-admin/css/themes.css src/wp-admin/css/themes.css
index 565f2fa..fc39880 100644
--- src/wp-admin/css/themes.css
+++ src/wp-admin/css/themes.css
@@ -1357,6 +1357,13 @@ body.full-overlay-active {
 	height: 100%;
 }
 
+#customize-preview.wp-full-overlay-main {
+	background: url(../images/spinner.gif) no-repeat;
+	-webkit-background-size: 20px 20px;
+	background-size: 20px 20px;
+	background-position: center center;
+}
+
 .wp-full-overlay-sidebar .wp-full-overlay-header {
 	position: absolute;
 	left: 0;
diff --git src/wp-admin/js/customize-controls.js src/wp-admin/js/customize-controls.js
index 7c4a631..c85af04 100644
--- src/wp-admin/js/customize-controls.js
+++ src/wp-admin/js/customize-controls.js
@@ -1769,6 +1769,9 @@
 		refresh: function() {
 			var self = this;
 
+			// Display loading indicator
+			this.send( 'loading-initiated' );
+
 			this.abort();
 
 			this.loading = new api.PreviewFrame({
@@ -1801,8 +1804,10 @@
 			});
 
 			this.loading.fail( function( reason, location ) {
-				if ( 'redirect' === reason && location )
+				self.send( 'loading-failed' );
+				if ( 'redirect' === reason && location ) {
 					self.previewUrl( location );
+				}
 
 				if ( 'logged out' === reason ) {
 					if ( self.preview ) {
@@ -1813,8 +1818,9 @@
 					self.login().done( self.refresh );
 				}
 
-				if ( 'cheatin' === reason )
+				if ( 'cheatin' === reason ) {
 					self.cheatin();
+				}
 			});
 		},
 
diff --git src/wp-includes/class-wp-customize-manager.php src/wp-includes/class-wp-customize-manager.php
index b695271..b25b48a 100644
--- src/wp-includes/class-wp-customize-manager.php
+++ src/wp-includes/class-wp-customize-manager.php
@@ -432,6 +432,7 @@ final class WP_Customize_Manager {
 		add_action( 'wp', array( $this, 'customize_preview_override_404_status' ) );
 		add_action( 'wp_head', array( $this, 'customize_preview_base' ) );
 		add_action( 'wp_head', array( $this, 'customize_preview_html5' ) );
+		add_action( 'wp_head', array( $this, 'customize_preview_loading_style' ) );
 		add_action( 'wp_footer', array( $this, 'customize_preview_settings' ), 20 );
 		add_action( 'shutdown', array( $this, 'customize_preview_signature' ), 1000 );
 		add_filter( 'wp_die_handler', array( $this, 'remove_preview_signature' ) );
@@ -491,6 +492,20 @@ final class WP_Customize_Manager {
 		<![endif]--><?php
 	}
 
+	public function customize_preview_loading_style() {
+		?><style>
+			body.wp-customizer-unloading {
+				opacity: 0.25;
+				cursor: progress !important;
+				-webkit-transition: opacity 0.5s;
+				transition: opacity 0.5s;
+			}
+			body.wp-customizer-unloading * {
+				pointer-events: none !important;
+			}
+		</style><?php
+	}
+
 	/**
 	 * Print JavaScript settings for preview frame.
 	 *
@@ -503,6 +518,9 @@ final class WP_Customize_Manager {
 			'activePanels' => array(),
 			'activeSections' => array(),
 			'activeControls' => array(),
+			'l10n' => array(
+				'loading'  => __( 'Loading ...' ),
+			),
 		);
 
 		if ( 2 == $this->nonce_tick ) {
diff --git src/wp-includes/js/customize-preview.js src/wp-includes/js/customize-preview.js
index 82f7bb8..d02f8f9 100644
--- src/wp-includes/js/customize-preview.js
+++ src/wp-includes/js/customize-preview.js
@@ -115,6 +115,16 @@
 			activeControls: api.settings.activeControls
 		} );
 
+		// Display a loading indicator when preview is reloading, and remove on failure
+		api.preview.bind( 'loading-initiated', function () {
+			$( 'body' ).addClass( 'wp-customizer-unloading' );
+			$( 'html' ).prop( 'title', api.settings.l10n.loading );
+		});
+		api.preview.bind( 'loading-failed', function () {
+			$( 'body' ).removeClass( 'wp-customizer-unloading' );
+			$( 'html' ).prop( 'title', '' );
+		});
+
 		/* Custom Backgrounds */
 		bg = $.map(['color', 'image', 'position_x', 'repeat', 'attachment'], function( prop ) {
 			return 'background_' + prop;
