diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 0092743f96ef1559049b465afe2223f370c088e4..a910d3d7c9d4d79eadda4dc102c272567aa47fec 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -129,7 +129,7 @@ def dropdown_footer(add_content_class: false, &block)
   end
 
   def dropdown_loading
-    spinner = loading_icon(container: true, size: "md", css_class: "gl-mt-7")
+    spinner = gl_loading_icon(size: "md", css_class: "gl-mt-7")
     content_tag(:div, spinner, class: "dropdown-loading")
   end
 end
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 32d808c960c0b3042907c1b25dbc84c28ce7f051..6f7ac069fe4878eba1d9f314f43dfe969dc40529 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -49,13 +49,39 @@ def sprite_icon(icon_name, size: DEFAULT_ICON_SIZE, css_class: nil)
     end
   end
 
-  def loading_icon(container: false, color: 'orange', size: 'sm', css_class: nil)
-    css_classes = ['gl-spinner', "gl-spinner-#{color}", "gl-spinner-#{size}"]
-    css_classes << "#{css_class}" unless css_class.blank?
-
-    spinner = content_tag(:span, "", { class: css_classes.join(' '), aria: { label: _('Loading') } })
-
-    container == true ? content_tag(:div, spinner, { class: 'gl-spinner-container' }) : spinner
+  # Creates a GitLab UI loading icon/spinner.
+  #
+  # Examples:
+  #   # Default
+  #   gl_loading_icon
+  #
+  #   # Sizes
+  #   gl_loading_icon(size: 'md')
+  #   gl_loading_icon(size: 'lg')
+  #   gl_loading_icon(size: 'xl')
+  #
+  #   # Colors
+  #   gl_loading_icon(color: 'light')
+  #
+  #   # Block/Inline
+  #   gl_loading_icon(inline: true)
+  #
+  #   # Custom classes
+  #   gl_loading_icon(css_class: "foo-bar")
+  #
+  # See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-loading-icon--default
+  def gl_loading_icon(inline: false, color: 'dark', size: 'sm', css_class: nil)
+    spinner = content_tag(:span, "", {
+      class: %[gl-spinner gl-spinner-#{color} gl-spinner-#{size} gl-vertical-align-text-bottom!],
+      aria: { label: _('Loading') }
+    })
+
+    container_classes = ['gl-spinner-container']
+    container_classes << css_class unless css_class.blank?
+    content_tag(inline ? :span : :div, spinner, {
+      class: container_classes,
+      role: 'status'
+    })
   end
 
   def external_snippet_icon(name)
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 2f4a61865f85e7f9646c8a58a5af57244725ed3b..a7cf50623f0c927ecb871ff604daafbc84cdf8f1 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -12,8 +12,7 @@
 
   .info-well.gl-display-none.gl-sm-display-flex.project-last-commit.gl-flex-direction-column
     #js-last-commit.gl-m-auto
-      .gl-spinner-container.m-auto
-        = loading_icon(size: 'md', color: 'dark', css_class: 'align-text-bottom')
+      = gl_loading_icon(size: 'md')
     #js-code-owners
 
   - if is_project_overview
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 919cafe7ce8aed5104028071d1055bd75941ca90..85b9a69ab4cc67945f83b8bc0f09abf1390e3c0e 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -21,8 +21,7 @@
                               project_path: @project.full_path,
                               target_branch: project.empty_repo? ? ref : @ref,
                               original_branch: @ref } }
-      .gl-spinner-container
-        = loading_icon(size: 'md')
+      = gl_loading_icon(size: 'md')
   - else
     %article.file-holder
       = render 'projects/blob/header', blob: blob
diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
index cf57f1b531d7ea9313f14557c73287a58eb7d191..2b8f62d98bf88b6230ea180d3427e93790995cac 100644
--- a/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
+++ b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml
@@ -1,4 +1,4 @@
-= loading_icon(css_class: "gl-vertical-align-text-bottom mr-1")
+= gl_loading_icon(inline: true, css_class: "gl-mr-2!")
 = s_('Pipelines|Validating GitLab CI configuration…')
 
 = link_to _('Learn more'), help_page_path('ci/yaml/index')
diff --git a/app/views/projects/blob/viewers/_loading.html.haml b/app/views/projects/blob/viewers/_loading.html.haml
index 18fd0d87ce63d4fe69921439194038da9f2245b1..9cb934da7c0a010f7f53aa239fc0a136a6e804b5 100644
--- a/app/views/projects/blob/viewers/_loading.html.haml
+++ b/app/views/projects/blob/viewers/_loading.html.haml
@@ -1,2 +1 @@
-.text-center.gl-mt-4.gl-mb-3
-  = loading_icon(size: "md", css_class: "qa-spinner")
+= gl_loading_icon(size: "md", css_class: "qa-spinner gl-my-4")
diff --git a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
index 5a2212e0b4eb511141918dfafb78853407087561..19aa96a930220dd45b9fdca0ba5212ab7b8f007d 100644
--- a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
+++ b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
@@ -1,2 +1,2 @@
-= loading_icon(css_class: "gl-vertical-align-text-bottom")
+= gl_loading_icon(inline: true)
 = _("Analyzing file…")
diff --git a/app/views/projects/blob/viewers/_metrics_dashboard_yml_loading.html.haml b/app/views/projects/blob/viewers/_metrics_dashboard_yml_loading.html.haml
index db4b04eaeb8803f0a2b8b4a14a6ef2d360af63dd..5e355ecc4b8ccad705e9588614d85238b36f5a51 100644
--- a/app/views/projects/blob/viewers/_metrics_dashboard_yml_loading.html.haml
+++ b/app/views/projects/blob/viewers/_metrics_dashboard_yml_loading.html.haml
@@ -1,4 +1,4 @@
-= loading_icon(css_class: "gl-vertical-align-text-bottom mr-1")
+= gl_loading_icon(inline: true, css_class: "mr-1")
 = _('Metrics Dashboard YAML definition') + '…'
 
 = link_to _('Learn more'), help_page_path('operations/metrics/dashboards/yaml.md')
diff --git a/app/views/projects/blob/viewers/_route_map_loading.html.haml b/app/views/projects/blob/viewers/_route_map_loading.html.haml
index c48ab84654f0ce17b2d4594d4f50e11ddc33c9c8..d9e965246a82820d48945b0821f897f580c81069 100644
--- a/app/views/projects/blob/viewers/_route_map_loading.html.haml
+++ b/app/views/projects/blob/viewers/_route_map_loading.html.haml
@@ -1,4 +1,4 @@
-= loading_icon(css_class: "gl-vertical-align-text-bottom gl-mr-1")
+= gl_loading_icon(inline: true, css_class: "gl-mr-1")
 Validating Route Map…
 
 = link_to 'Learn more', help_page_path('ci/environments/index.md', anchor: 'go-from-source-files-to-public-pages')
diff --git a/app/views/projects/blob/viewers/_sketch.html.haml b/app/views/projects/blob/viewers/_sketch.html.haml
index 08c21258d3fc858586a1064802dc1a03004909cc..4feaa7392fd74fb25fa25adc4df15c65e5da3df5 100644
--- a/app/views/projects/blob/viewers/_sketch.html.haml
+++ b/app/views/projects/blob/viewers/_sketch.html.haml
@@ -1,3 +1,2 @@
 .file-content#js-sketch-viewer{ data: { endpoint: blob_raw_path } }
-  .text-center.gl-mt-4.gl-mb-3.js-loading-icon
-    = loading_icon(size: "md")
+  = gl_loading_icon(size: "md", css_class: "gl-my-4 js-loading-icon")
diff --git a/app/views/projects/blob/viewers/_stl.html.haml b/app/views/projects/blob/viewers/_stl.html.haml
index f98deebacf9ff8da5ff214d8b37bb33689faf095..8bf0339fc3c1e00eee3a88d8d8856e91b351f416 100644
--- a/app/views/projects/blob/viewers/_stl.html.haml
+++ b/app/views/projects/blob/viewers/_stl.html.haml
@@ -1,6 +1,6 @@
 .file-content.is-stl-loading
   .text-center#js-stl-viewer{ data: { endpoint: blob_raw_path } }
-    = loading_icon(size: "md", css_class: "gl-mt-4 gl-mb-3")
+    = gl_loading_icon(size: "md", css_class: "gl-my-4")
   .text-center.gl-mt-3.gl-mb-3.stl-controls
     .btn-group
       %button.gl-button.btn.btn-default.btn-sm.js-material-changer{ data: { type: 'wireframe' } }
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 22a5bada3117b4fb28addc2698bf7d03f973a7fb..36641a8c508fd6f6e0e4843ce7d0e755c3e265da 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -34,5 +34,4 @@
   %div{ id: dom_id(@project) }
     %ol#commits-list.list-unstyled.content_list
       = render 'commits', project: @project, ref: @ref
-  .loading.hide
-    = loading_icon(size: "lg")
+  = gl_loading_icon(size: 'lg', css_class: 'loading hide')
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 194b10e9ef4f7c655976c0df977b2f2ed80dddf0..af5ad06d30e8d3600b20b36fab7acaab60b162f4 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -23,5 +23,4 @@
               = _('There are no matching files')
             %p.text-secondary
               = _('Try using a different search term to find the file you are looking for.')
-      .text-center.gl-mt-3.loading
-        = loading_icon(size: 'md')
+      = gl_loading_icon(size: 'md', css_class: 'gl-mt-3 loading')
diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml
index 0c1efab21951fb8ed993e29fb05aecff6547a498..8096bc6cead940c161f60b303e108fb0825d646f 100644
--- a/app/views/projects/imports/show.html.haml
+++ b/app/views/projects/imports/show.html.haml
@@ -4,7 +4,7 @@
 .save-project-loader
   .center
     %h2
-      = loading_icon
+      = gl_loading_icon(inline: true)
       = import_in_progress_title
     - if !has_ci_cd_only_params? && @project.external_import?
       %p.monospace git clone --bare #{@project.safe_import_url}
diff --git a/app/views/projects/services/prometheus/_custom_metrics.html.haml b/app/views/projects/services/prometheus/_custom_metrics.html.haml
index 4586ee844c0b7cb3802dc85d71e912931f24cd4e..896249c6163cab25de92a759d9de718ccbcb224b 100644
--- a/app/views/projects/services/prometheus/_custom_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_custom_metrics.html.haml
@@ -18,7 +18,7 @@
           .flash-text
       .loading-metrics.js-loading-custom-metrics
         %p.m-3
-          = loading_icon(css_class: 'metrics-load-spinner')
+          = gl_loading_icon(inline: true, css_class: 'metrics-load-spinner')
           = s_('PrometheusService|Finding custom metrics...')
       .empty-metrics.hidden.js-empty-custom-metrics
         %p.text-tertiary.m-3.js-no-active-integration-text.hidden
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 0d41584652f95ebb66acb2d1b58454250d9515c8..8794f3e24dae2075b6626f330720cb81e5eb7b49 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -16,7 +16,7 @@
     .card-body
       .loading-metrics.js-loading-metrics
         %p.m-3
-          = loading_icon(css_class: 'metrics-load-spinner')
+          = gl_loading_icon(inline: true, css_class: 'metrics-load-spinner')
           = s_('PrometheusService|Finding and configuring metrics...')
       .empty-metrics.hidden.js-empty-metrics
         %p.text-tertiary.m-3
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
index 08003346d09043573b023ca336d2a884ec56bb4f..74a397d7a03f4611adb42cd3e7ba1b5bfcd93c6c 100644
--- a/app/views/shared/_new_project_item_select.html.haml
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -1,7 +1,7 @@
 - if any_projects?(@projects)
   .project-item-select-holder.btn-group.gl-ml-auto.gl-mr-auto.gl-relative.gl-overflow-hidden{ class: 'gl-display-flex!' }
     %a.btn.gl-button.btn-confirm.js-new-project-item-link.block-truncated.qa-new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] }, class: "gl-m-0!" }
-      = loading_icon(color: 'light')
+      = gl_loading_icon(inline: true, color: 'light')
     = project_select_tag :project_path, class: "project-item-select gl-absolute! gl-visibility-hidden", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path], with_shared: local_assigns[:with_shared], include_projects_in_subgroups: local_assigns[:include_projects_in_subgroups] }, with_feature_enabled: local_assigns[:with_feature_enabled]
     %button.btn.dropdown-toggle.btn-confirm.btn-md.gl-button.gl-dropdown-toggle.dropdown-toggle-split.new-project-item-select-button.qa-new-project-item-select-button.gl-p-0.gl-w-100{ class: "gl-m-0!", 'aria-label': _('Toggle project select') }
       = sprite_icon('chevron-down')
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 7787e5dd66080d020cd0a44132ff2899ecd3e151..f966958d2c73c687dc9db4fcd5d8459fac999a16 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -50,7 +50,7 @@
           // Fallback while content is loading
           .title.hide-collapsed
             = _('Time tracking')
-            = loading_icon(css_class: 'gl-vertical-align-text-bottom')
+            = gl_loading_icon(inline: true)
       - if issuable_sidebar.has_key?(:due_date)
         #js-due-date-entry-point
 
@@ -109,8 +109,8 @@
               = dropdown_loading
               = dropdown_footer add_content_class: true do
                 %button.gl-button.btn.btn-confirm.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ type: 'button', disabled: true }
+                  = gl_loading_icon(inline: true, css_class: 'sidebar-move-issue-confirmation-loading-icon gl-mr-2')
                   = _('Move')
-                  = loading_icon(css_class: 'gl-vertical-align-text-bottom sidebar-move-issue-confirmation-loading-icon')
 
     -# haml-lint:disable InlineJavaScript
     %script.js-sidebar-options{ type: "application/json" }= issuable_sidebar_options(issuable_sidebar).to_json.html_safe
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index 9a0b25f401536390c8a615fb0753d8b15426dcc0..2fd4c598580c23a31cef3de145653b6f5bcf4f2d 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -7,7 +7,7 @@
   directly_invite_members: can_admin_project_member?(@project) } }
   .title.hide-collapsed
     = _('Assignee')
-    = loading_icon(css_class: 'gl-vertical-align-text-bottom')
+    = gl_loading_icon(inline: true)
 
 .js-sidebar-assignee-data.selectbox.hide-collapsed
   - if assignees.none?
diff --git a/app/views/shared/issuable/_sidebar_reviewers.html.haml b/app/views/shared/issuable/_sidebar_reviewers.html.haml
index bc76d292dd64b207361249f5198ab186fdd5d57a..ce252e7457081c2ec8904ad90e6c3b6e5438aa39 100644
--- a/app/views/shared/issuable/_sidebar_reviewers.html.haml
+++ b/app/views/shared/issuable/_sidebar_reviewers.html.haml
@@ -3,7 +3,7 @@
 #js-vue-sidebar-reviewers{ data: { field: issuable_type, signed_in: signed_in } }
   .title.hide-collapsed
     = _('Reviewer')
-    = loading_icon(css_class: 'gl-vertical-align-text-bottom')
+    = gl_loading_icon(inline: true)
 
 .selectbox.hide-collapsed
   - if reviewers.none?
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index 6c8b2a9e5bb392dbb110744ec01bc8333c6ec304..8a79a17b16653d47bd31998fae38d501828f349c 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -18,7 +18,7 @@
         %span.attaching-file-message
           -# Populated by app/assets/javascripts/dropzone_input.js
         %span.uploading-progress 0%
-        = loading_icon(css_class: 'align-text-bottom gl-mr-2')
+        = gl_loading_icon(inline: true, css_class: 'gl-mr-2')
 
       %span.uploading-error-container.hide
         %span.uploading-error-icon
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index 3f7490b0221aae0b246f9f90b3a2facef28da833..d107af156db631a9f02f3c8f6b73c2e90639cb05 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -88,50 +88,36 @@ Please use the following function inside JS to render an icon:
 
 ### Usage in HAML/Rails
 
-To insert a loading spinner in HAML or Rails use the `loading_icon` helper:
+To insert a loading spinner in HAML or Rails use the `gl_loading_icon` helper:
 
 ```haml
-= loading_icon
+= gl_loading_icon
 ```
 
-You can include one or more of the following properties with the `loading_icon` helper, as demonstrated
+You can include one or more of the following properties with the `gl_loading_icon` helper, as demonstrated
 by the examples that follow:
 
-- `container` (optional): wraps the loading icon in a container, which centers the loading icon using the `text-center` CSS property.
-- `color` (optional): either `orange` (default), `light`, or `dark`.
+- `inline` (optional): uses in an inline element if `true`, otherwise, a block element (default), with the spinner centered.
+- `color` (optional): either `dark` (default) or `light`.
 - `size` (optional): either `sm` (default), `md`, `lg`, or `xl`.
-- `css_class` (optional): defaults to an empty string, but can be used for utility classes to fine-tune alignment or spacing.
+- `css_class` (optional): defaults to nothing, but can be used for utility classes to fine-tune alignment or spacing.
 
 **Example 1:**
 
 The following HAML expression generates a loading icon's markup and
-centers the icon by wrapping it in a `gl-spinner-container` element.
+centers the icon.
 
 ```haml
-= loading_icon(container: true)
-```
-
-**Output from example 1:**
-
-```html
-<div class="gl-spinner-container">
-  <span class="gl-spinner gl-spinner-orange gl-spinner-sm" aria-label="Loading"></span>
-</div>
+= gl_loading_icon
 ```
 
 **Example 2:**
 
-The following HAML expression generates a loading icon's markup
+The following HAML expression generates an inline loading icon's markup
 with a custom size. It also appends a margin utility class.
 
 ```haml
-= loading_icon(size: 'lg', css_class: 'gl-mr-2')
-```
-
-**Output from example 2:**
-
-```html
-<span class="gl-spinner gl-spinner-orange gl-spinner-lg gl-mr-2" aria-label="Loading"></span>
+= gl_loading_icon(inline: true, size: 'lg', css_class: 'gl-mr-2')
 ```
 
 ### Usage in Vue
diff --git a/spec/helpers/icons_helper_spec.rb b/spec/helpers/icons_helper_spec.rb
index af2957d72c7bc7b184f12dccdbce4607631c49bb..139e8be33d54ad09915ef213308093caedbc71d1 100644
--- a/spec/helpers/icons_helper_spec.rb
+++ b/spec/helpers/icons_helper_spec.rb
@@ -231,23 +231,33 @@
     end
   end
 
-  describe 'loading_icon' do
-    it 'returns span with gl-spinner class and default configuration' do
-      expect(loading_icon.to_s)
-        .to eq '<span class="gl-spinner gl-spinner-orange gl-spinner-sm" aria-label="Loading"></span>'
+  describe 'gl_loading_icon' do
+    it 'returns the default spinner markup' do
+      expect(gl_loading_icon.to_s)
+        .to eq '<div class="gl-spinner-container" role="status"><span class="gl-spinner gl-spinner-dark gl-spinner-sm gl-vertical-align-text-bottom!" aria-label="Loading"></span></div>'
     end
 
     context 'when css_class is provided' do
-      it 'appends css_class to gl-spinner element' do
-        expect(loading_icon(css_class: 'gl-mr-2').to_s)
-          .to eq '<span class="gl-spinner gl-spinner-orange gl-spinner-sm gl-mr-2" aria-label="Loading"></span>'
+      it 'appends css_class to container element' do
+        expect(gl_loading_icon(css_class: 'gl-mr-2').to_s).to match 'gl-spinner-container gl-mr-2'
       end
     end
 
-    context 'when container is true' do
-      it 'creates a container that has the gl-spinner-container class selector' do
-        expect(loading_icon(container: true).to_s)
-        .to eq '<div class="gl-spinner-container"><span class="gl-spinner gl-spinner-orange gl-spinner-sm" aria-label="Loading"></span></div>'
+    context 'when size is provided' do
+      it 'sets the size class' do
+        expect(gl_loading_icon(size: 'xl').to_s).to match 'gl-spinner-xl'
+      end
+    end
+
+    context 'when color is provided' do
+      it 'sets the color class' do
+        expect(gl_loading_icon(color: 'light').to_s).to match 'gl-spinner-light'
+      end
+    end
+
+    context 'when inline is true' do
+      it 'creates an inline container' do
+        expect(gl_loading_icon(inline: true).to_s).to start_with '<span class="gl-spinner-container"'
       end
     end
   end