diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 705d592..ef3167d 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -461,10 +461,11 @@
       $(this.element).after(this.progress.element);
     }
     else if (this.progress.type === 'throbber') {
-      this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber">&nbsp;</div></div>');
-      if (this.progress.message) {
-        this.progress.element.find('.throbber').after('<div class="message">' + this.progress.message + '</div>');
-      }
+      var throbber = new Drupal.ProgressThrobber('ajax-progress-throbber-element', $.noop, this.progress.method, $.noop);
+      throbber.startMonitoring();
+      Drupal.announce(this.progress.message);
+      this.progress.element = $(throbber.element).addClass('ajax-progress ajax-progress-throbber is-loading');
+      this.progress.object = throbber;
       $(this.element).after(this.progress.element);
     }
     else if (this.progress.type === 'fullscreen') {
diff --git a/core/misc/progress.js b/core/misc/progress.js
index 52127e6..b45b301 100644
--- a/core/misc/progress.js
+++ b/core/misc/progress.js
@@ -109,4 +109,83 @@
     }
   });
 
+    Drupal.ProgressThrobber = function (id, updateCallback, method, errorCallback) {
+        this.id = id;
+        this.method = method || 'GET';
+        this.updateCallback = updateCallback;
+        this.errorCallback = errorCallback;
+
+        // The WAI-ARIA setting aria-live="polite" will announce changes after users
+        // have completed their current activity and not interrupt the screen reader.
+        this.element = $('<div class="progress" aria-live="polite"></div>');
+        this.element.html('<div class="throbber" aria-live="polite""></div>');
+
+    };
+
+    $.extend(Drupal.ProgressThrobber.prototype, {
+
+        /**
+         * Start monitoring progress via Ajax.
+         */
+        startMonitoring: function (uri, delay) {
+            this.delay = delay;
+            this.uri = uri;
+            this.sendPing();
+        },
+
+        /**
+         * Stop monitoring progress via Ajax.
+         */
+        stopMonitoring: function () {
+            clearTimeout(this.timer);
+            // This allows monitoring to be stopped from within the callback.
+            this.uri = null;
+        },
+
+        /**
+         * Request progress data from server.
+         */
+        sendPing: function () {
+            if (this.timer) {
+                clearTimeout(this.timer);
+            }
+            if (this.uri) {
+                var throbber = this;
+                // When doing a post request, you need non-null data. Otherwise a
+                // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
+                $.ajax({
+                    type: this.method,
+                    url: this.uri,
+                    data: '',
+                    dataType: 'json',
+                    success: function (progress) {
+                        // Display errors.
+                        if (progress.status === 0) {
+                            throbber.displayError(progress.data);
+                            return;
+                        }
+                        // Schedule next timer.
+                        throbber.timer = setTimeout(function () { throbber.sendPing(); }, throbber.delay);
+                    },
+                    error: function (xmlhttp) {
+                        var e = new Drupal.AjaxError(xmlhttp, throbber.uri);
+                        throbber.displayError('<pre>' + e.message + '</pre>');
+                    }
+                });
+            }
+        },
+
+        /**
+         * Display errors on the page.
+         */
+        displayError: function (string) {
+            var error = $('<div class="messages messages--error"></div>').html(string);
+            $(this.element).before(error).hide();
+
+            if (this.errorCallback) {
+                this.errorCallback(this);
+            }
+        }
+    });
+
 })(jQuery);
diff --git a/core/modules/quickedit/css/quickedit.icons.css b/core/modules/quickedit/css/quickedit.icons.css
index 7845416..2455f69 100644
--- a/core/modules/quickedit/css/quickedit.icons.css
+++ b/core/modules/quickedit/css/quickedit.icons.css
@@ -64,9 +64,7 @@
 .quickedit .icon-close:active:before {
   background-image: url(../../../misc/icons/000000/ex.svg);
 }
-.quickedit .icon-throbber:before {
-  background-image: url(../images/icon-throbber.gif);
-}
+
 .quickedit .icon-pencil:before {
   background-image: url(../../../misc/icons/5181c6/pencil.svg);
   background-position: left center;
diff --git a/core/modules/quickedit/css/quickedit.theme.css b/core/modules/quickedit/css/quickedit.theme.css
index 8d9e198..4cd8935 100644
--- a/core/modules/quickedit/css/quickedit.theme.css
+++ b/core/modules/quickedit/css/quickedit.theme.css
@@ -240,11 +240,27 @@
 .quickedit-button.action-save:active {
   border: 1px solid #a0a0a0;
 }
-.quickedit-button.action-saving,
-.quickedit-button.action-saving:hover,
-.quickedit-button.action-saving:active {
-  background-color: #e4e4e4;
-  background-image: none;
-  border-color: #d2d2d2;
-  color: #5a5a5a;
+
+.quickedit-button.action-save.is-loading::before,
+.quickedit-button.action-save.is-loading::after {
+  content: none;
+}
+
+.quickedit-button.action-save.is-loading {
+  background: url(../../../misc/throbber.gif) no-repeat 95% center,
+  -webkit-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../misc/throbber.gif) no-repeat 95% center,
+  -moz-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../misc/throbber.gif) no-repeat 95% center,
+  -o-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../misc/throbber.gif) no-repeat 95% center,
+  linear-gradient(to bottom, #007bc6, #0071b8);
+}
+
+[dir="ltr"] .quickedit-button.action-save.is-loading {
+  padding-right: 25px; /* LTR */
+}
+
+[dir="rtl"] .quickedit-button.action-save.is-loading {
+   padding-left: 25px;
 }
diff --git a/core/modules/quickedit/js/views/EntityToolbarView.js b/core/modules/quickedit/js/views/EntityToolbarView.js
index 0cd7f0d..e5f0265 100644
--- a/core/modules/quickedit/js/views/EntityToolbarView.js
+++ b/core/modules/quickedit/js/views/EntityToolbarView.js
@@ -93,7 +93,7 @@
           // The saving throbber is not managed by AJAX system. The
           // EntityToolbarView manages this visual element.
           $button
-            .removeClass('action-saving icon-throbber icon-end')
+            .removeClass('ajax-progress ajax-progress-throbber is-loading')
             .text(Drupal.t('Save'))
             .removeAttr('disabled')
             .attr('aria-hidden', !isDirty);
@@ -101,7 +101,7 @@
         // The changes to the fields of the entity are being committed.
         case 'committing':
           $button
-            .addClass('action-saving icon-throbber icon-end')
+            .addClass('ajax-progress ajax-progress-throbber is-loading')
             .text(Drupal.t('Saving'))
             .attr('disabled', 'disabled');
           break;
diff --git a/core/modules/system/css/system.module.css b/core/modules/system/css/system.module.css
index cea7a25..7482732 100644
--- a/core/modules/system/css/system.module.css
+++ b/core/modules/system/css/system.module.css
@@ -238,7 +238,7 @@ table.sticky-header {
 .ajax-progress-throbber .throbber {
   background: transparent url(../../../misc/throbber-active.gif) no-repeat 0px center;
   display: inline;
-  padding: 1px 5px 2px;
+  padding: 1px 6px 2px;
 }
 .ajax-progress-throbber .message {
   display: inline;
diff --git a/core/themes/seven/css/components/buttons.theme.css b/core/themes/seven/css/components/buttons.theme.css
index e5f0e1d..33306e8 100644
--- a/core/themes/seven/css/components/buttons.theme.css
+++ b/core/themes/seven/css/components/buttons.theme.css
@@ -54,6 +54,30 @@
           transition: none;
 }
 
+[dir="ltr"] .button.ajax-progress-throbber.is-loading {
+  background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+  -webkit-linear-gradient(top, #f6f6f3, #e7e7df);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+  -moz-linear-gradient(top, #f6f6f3, #e7e7df);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+  -o-linear-gradient(top, #f6f6f3, #e7e7df);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+  linear-gradient(to bottom, #f6f6f3, #e7e7df);
+  padding-right: 2em;
+}
+
+[dir="rtl"] .button.ajax-progress-throbber.is-loading {
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  -webkit-linear-gradient(top, #f6f6f3, #e7e7df);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  -moz-linear-gradient(top, #f6f6f3, #e7e7df);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  -o-linear-gradient(top, #f6f6f3, #e7e7df);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  linear-gradient(to bottom, #f6f6f3, #e7e7df);
+  padding-left: 2em;
+}
+
 .button--primary {
   border-color: #1e5c90;
   background-color: #0071b8;
@@ -85,6 +109,28 @@
   box-shadow: inset 0 1px 3px hsla(0, 0%, 0%, 0.2);
 }
 
+.button--primary.ajax-progress-throbber.is-loading {
+  background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+  -webkit-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+ -moz-linear-gradient(top, #007bc6, #0071b8);
+ background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+ -o-linear-gradient(top, #007bc6, #0071b8);
+ background: url(../../../../misc/throbber-active.gif) no-repeat 95% center,
+ linear-gradient(to bottom, #007bc6, #0071b8);
+}
+
+[dir="rtl"] .button--primary.ajax-progress-throbber.is-loading {
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  -webkit-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  -moz-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  -o-linear-gradient(top, #007bc6, #0071b8);
+  background: url(../../../../misc/throbber-active.gif) no-repeat 5% center,
+  linear-gradient(to bottom, #007bc6, #0071b8);
+}
+
 /**
  * Overrides styling from system.theme.
  */
@@ -119,6 +165,10 @@
   text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
 }
 
+.button:disabled.ajax-progress-throbber.is-loading {
+  background: #ededed url(../../../../misc/throbber-active.gif) no-repeat 95% center;
+}
+
 /* Link actions. */
 
 /**
diff --git a/core/themes/seven/css/components/form.css b/core/themes/seven/css/components/form.css
index 5dacb03..9493b08 100644
--- a/core/themes/seven/css/components/form.css
+++ b/core/themes/seven/css/components/form.css
@@ -168,6 +168,20 @@ textarea.form-textarea {
   background-color: #fff;
 }
 
+input.form-autocomplete.is-loading,
+input.form-text.is-loading,
+input.form-tel.is-loading,
+input.form-email.is-loading,
+input.form-url.is-loading,
+input.form-search.is-loading,
+input.form-number.is-loading,
+input.form-color.is-loading,
+input.form-file.is-loading,
+textarea.form-textarea.is-loading,
+select.form-select.is-loading {
+  background: #fff url(../../../../misc/throbber-active.gif) no-repeat 95% center;
+}
+
 .confirm-parent,
 .password-parent {
   overflow: visible;

