diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php
index 63671576b2..b793a341bc 100644
--- a/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -120,7 +120,7 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
     // Populate the 'array_parents' information in $form_state->get('field')
     // after the form is built, so that we catch changes in the form structure
     // performed in alter() hooks.
-    $elements['#after_build'][] = [get_class($this), 'afterBuild'];
+    $elements['#after_build'][] = [static::class, 'afterBuild'];
     $elements['#field_name'] = $field_name;
     $elements['#field_parents'] = $parents;
     // Enforce the structure of submitted values.
@@ -156,12 +156,12 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
     $field_name = $this->fieldDefinition->getName();
     $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
     $parents = $form['#parents'];
+    $field_state = static::getWidgetState($parents, $field_name, $form_state);
 
     // Determine the number of widgets to display.
     switch ($cardinality) {
       case FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED:
-        $field_state = static::getWidgetState($parents, $field_name, $form_state);
-        $max = $field_state['items_count'];
+        $max = $field_state['items_count'] - 1;
         $is_multiple = TRUE;
         break;
 
@@ -173,6 +173,8 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
 
     $title = $this->fieldDefinition->getLabel();
     $description = FieldFilteredMarkup::create(\Drupal::token()->replace($this->fieldDefinition->getDescription()));
+    $id_prefix = implode('-', array_merge($parents, [$field_name]));
+    $wrapper_id = Html::GetUniqueId($id_prefix . '-add-wrapper');
 
     $elements = [];
 
@@ -212,48 +214,69 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
             '#title_display' => 'invisible',
             // Note: this 'delta' is the FAPI #type 'weight' element's property.
             '#delta' => $max,
-            '#default_value' => $items[$delta]->_weight ?: $delta,
+            '#value' => $items[$delta]->_weight ?: $delta,
             '#weight' => 100,
           ];
+          $element['actions'] = [
+            '#type' => 'actions',
+            'remove_button' => [
+              '#delta' => $delta,
+              //'#name' => implode('_', array_merge($field_state['array_parents'], [$field_name, $delta])) . '_remove_button',
+              // @TODO: Refactor. Probably want a more intuitive way to determine the #name
+              '#name' => implode('_', $element['#field_parents']) . "_remove_button_$delta",
+              '#type' => 'submit',
+              '#value' => t('Remove'),
+              '#validate' => [],
+              '#submit' => [[static::class, 'submitRemove']],
+              '#limit_validation_errors' => [],
+              '#attributes' => [
+                'class' => ['remove-field-delta--' . $delta],
+              ],
+              '#ajax' => [
+                'callback' => [static::class, 'removeAjaxContentRefresh'],
+                'wrapper' => $wrapper_id,
+                'effect' => 'fade',
+              ],
+            ],
+          ];
         }
 
         $elements[$delta] = $element;
       }
     }
 
-    if ($elements) {
-      $elements += [
-        '#theme' => 'field_multiple_value_form',
-        '#field_name' => $field_name,
-        '#cardinality' => $cardinality,
-        '#cardinality_multiple' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple(),
-        '#required' => $this->fieldDefinition->isRequired(),
-        '#title' => $title,
-        '#description' => $description,
-        '#max_delta' => $max,
+    $elements += [
+      '#theme' => 'field_multiple_value_form',
+      '#field_name' => $field_name,
+      '#cardinality' => $cardinality,
+      '#cardinality_multiple' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple(),
+      '#required' => $this->fieldDefinition->isRequired(),
+      '#title' => $title,
+      '#description' => $description,
+      '#max_delta' => $max,
+    ];
+
+    // Add 'add more' button, if not working with a programmed form.
+    if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && !$form_state->isProgrammed()) {
+
+      $form['#wrapper_id'] = $wrapper_id;
+      $elements['#prefix'] = '<div id="' . $wrapper_id . '">';
+      $elements['#suffix'] = '</div>';
+
+      $elements['add_more'] = [
+        '#type' => 'submit',
+        '#name' => strtr($id_prefix, '-', '_') . '_add_more',
+        '#value' => $delta > 0 ? t('Add another item') : t('Add item'),
+        '#attributes' => ['class' => ['field-add-more-submit']],
+        '#limit_validation_errors' => [],
+        '#submit' => [[static::class, 'addMoreSubmit']],
+        '#ajax' => [
+          'callback' => [static::class, 'addMoreAjax'],
+          'wrapper' => $wrapper_id,
+          'effect' => 'fade',
+        ],
       ];
 
-      // Add 'add more' button, if not working with a programmed form.
-      if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && !$form_state->isProgrammed()) {
-        $id_prefix = implode('-', array_merge($parents, [$field_name]));
-        $wrapper_id = Html::getUniqueId($id_prefix . '-add-more-wrapper');
-        $elements['#prefix'] = '<div id="' . $wrapper_id . '">';
-        $elements['#suffix'] = '</div>';
-
-        $elements['add_more'] = [
-          '#type' => 'submit',
-          '#name' => strtr($id_prefix, '-', '_') . '_add_more',
-          '#value' => t('Add another item'),
-          '#attributes' => ['class' => ['field-add-more-submit']],
-          '#limit_validation_errors' => [array_merge($parents, [$field_name])],
-          '#submit' => [[get_class($this), 'addMoreSubmit']],
-          '#ajax' => [
-            'callback' => [get_class($this), 'addMoreAjax'],
-            'wrapper' => $wrapper_id,
-            'effect' => 'fade',
-          ],
-        ];
-      }
     }
 
     return $elements;
@@ -320,6 +343,71 @@ public static function addMoreAjax(array $form, FormStateInterface $form_state)
     return $element;
   }
 
+  /**
+   * Ajax submit callback for the "Remove" button.
+   *
+   * This re-numbers form elements and removes an item.
+   */
+  public static function submitRemove(&$form, FormStateInterface $form_state) {
+    $button = $form_state->getTriggeringElement();
+    $delta = $button['#delta'];
+    $array_parents = array_slice($button['#array_parents'], 0, -4);
+    $old_parents = array_slice($button['#parents'], 0, -3);
+    $parent_element = NestedArray::getValue($form, array_merge($array_parents, ['widget']));
+    $field_name = $parent_element['#field_name'];
+    $parents = $parent_element['#field_parents'];
+    $field_state = static::getWidgetState($parents, $field_name, $form_state);
+    for ($i = $delta; $i < $field_state['items_count']; $i++) {
+      $old_element_widget_parents = array_merge($array_parents, ['widget', $i + 1]);
+      $old_element_parents = array_merge($old_parents, [$i + 1]);
+      $new_element_parents = array_merge($old_parents, [$i]);
+      $moving_element = NestedArray::getValue($form, $old_element_widget_parents);
+      $moving_element_input = NestedArray::getValue($form_state->getUserInput(), $old_element_parents);
+
+      // Tell the element where it's being moved to.
+      $moving_element['#parents'] = $new_element_parents;
+
+      // Move the element around.
+      $user_input = $form_state->getUserInput();
+      NestedArray::setValue($user_input, $moving_element['#parents'], $moving_element_input);
+      $user_input[$field_name] = array_filter(NestedArray::getValue($user_input, $old_parents));
+
+      $form_state->setUserInput($user_input);
+    }
+    unset($parent_element[$delta]);
+    NestedArray::setValue($form, $array_parents, $parent_element);
+
+    if ($field_state['items_count'] > 0) {
+      $field_state['items_count']--;
+    }
+    $key_exists = '';
+    unset($array_parents[1]);
+    $input = NestedArray::getValue($form_state->getUserInput(), $array_parents, $key_exists);
+
+    $weight = -1 * $field_state['items_count'];
+    foreach ($input as $key => $item) {
+      if ($item) {
+        $input[$key]['_weight'] = $weight++;
+      }
+    }
+    $user_input = $form_state->getUserInput();
+    NestedArray::setValue($user_input, $array_parents, $input);
+    $form_state->setUserInput($user_input);
+    static::setWidgetState($parents, $field_name, $form_state, $field_state);
+    $form_state->setRebuild();
+  }
+
+  /**
+   * Ajax refresh callback for the "Remove" button.
+   *
+   * This returns the new page content to replace the page content made obsolete
+   * by the form submission.
+   */
+  public static function removeAjaxContentRefresh(array &$form, FormStateInterface $form_state) {
+    $button = $form_state->getTriggeringElement();
+    return NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -4));
+  }
+
   /**
    * Generates the form element for a single copy of the widget.
    */
