diff --git a/core/includes/common.inc b/core/includes/common.inc
index 9ec0e86..7cced70 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1768,51 +1768,18 @@ function drupal_html_class($class) {
  *   The cleaned ID.
  */
 function drupal_html_id($id) {
-  // If this is an Ajax request, then content returned by this page request will
-  // be merged with content already on the base page. The HTML IDs must be
-  // unique for the fully merged content. Therefore, initialize $seen_ids to
-  // take into account IDs that are already in use on the base page.
-  $seen_ids_init = &drupal_static(__FUNCTION__ . ':init');
-  if (!isset($seen_ids_init)) {
-    $ajax_html_ids = \Drupal::request()->request->get('ajax_html_ids');
-    // Ideally, Drupal would provide an API to persist state information about
-    // prior page requests in the database, and we'd be able to add this
-    // function's $seen_ids static variable to that state information in order
-    // to have it properly initialized for this page request. However, no such
-    // page state API exists, so instead, ajax.js adds all of the in-use HTML
-    // IDs to the POST data of Ajax submissions. Direct use of $_POST is
-    // normally not recommended as it could open up security risks, but because
-    // the raw POST data is cast to a number before being returned by this
-    // function, this usage is safe.
-    if (empty($ajax_html_ids)) {
-      $seen_ids_init = array();
-    }
-    else {
-      // This function ensures uniqueness by appending a counter to the base id
-      // requested by the calling function after the first occurrence of that
-      // requested id. $_POST['ajax_html_ids'] contains the ids as they were
-      // returned by this function, potentially with the appended counter, so
-      // we parse that to reconstruct the $seen_ids array.
-      $ajax_html_ids = explode(' ', $ajax_html_ids);
-      foreach ($ajax_html_ids as $seen_id) {
-        // We rely on '--' being used solely for separating a base id from the
-        // counter, which this function ensures when returning an id.
-        $parts = explode('--', $seen_id, 2);
-        if (!empty($parts[1]) && is_numeric($parts[1])) {
-          list($seen_id, $i) = $parts;
-        }
-        else {
-          $i = 1;
-        }
-        if (!isset($seen_ids_init[$seen_id]) || ($i > $seen_ids_init[$seen_id])) {
-          $seen_ids_init[$seen_id] = $i;
-        }
-      }
-    }
+
+  $request_nonce = &drupal_static(__FUNCTION__ . ':nonce');
+  if (!isset($request_nonce)) {
+    // @todo The hash should not change for sub-requests, so it is not clear
+    //   whether relying on the Request object is appropriate. Verify this,
+    //   once there are sub-requests in core.
+    $request_nonce = uniqid();
   }
-  $seen_ids = &drupal_static(__FUNCTION__, $seen_ids_init);
+  $seen_ids = &drupal_static(__FUNCTION__, array());
 
   $id = drupal_clean_id_identifier($id);
+  $id .= '-' . $request_nonce;
   // Ensure IDs are unique by appending a counter after the first occurrence.
   // The counter needs to be appended with a delimiter that does not exist in
   // the base ID. Requiring a unique delimiter helps ensure that we really do
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index 09621b2..c57139f 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -370,16 +370,6 @@
       Drupal.detachBehaviors(this.$form.get(0), settings, 'serialize');
     }
 
-    // Prevent duplicate HTML ids in the returned markup.
-    // @see drupal_html_id()
-    var ids = document.querySelectorAll('[id]');
-    var ajaxHtmlIds = [];
-    for (var i = 0, il = ids.length; i < il; i++) {
-      ajaxHtmlIds.push(ids[i].id);
-    }
-    // Join IDs to minimize request size.
-    options.data.ajax_html_ids = ajaxHtmlIds.join(' ');
-
     // Allow Drupal to return new JavaScript and CSS files to load without
     // returning the ones already loaded.
     // @see \Drupal\Core\Theme\AjaxBasePageNegotiator
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 61c54d1..58087f0 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -1540,7 +1540,7 @@ protected function drupalPostForm($path, $edit, $submit, array $options = array(
       // Let's iterate over all the forms.
       $xpath = "//form";
       if (!empty($form_html_id)) {
-        $xpath .= "[@id='" . $form_html_id . "']";
+        $xpath .= $xpath .= "[starts-with(@id, '" . $form_html_id . "')]";
       }
       $forms = $this->xpath($xpath);
       foreach ($forms as $form) {
@@ -1677,7 +1677,7 @@ protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_p
         $xpath = '//*[@name="' . $triggering_element . '"]';
       }
       if (isset($form_html_id)) {
-        $xpath = '//form[@id="' . $form_html_id . '"]' . $xpath;
+        $xpath = '//form[starts-with(@id, "' . $form_html_id . '")]' . $xpath;
       }
       $element = $this->xpath($xpath);
       $element_id = (string) $element[0]['id'];
@@ -1691,13 +1691,6 @@ protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_p
         $extra_post[$key] = $value;
       }
     }
-    $ajax_html_ids = array();
-    foreach ($this->xpath('//*[@id]') as $element) {
-      $ajax_html_ids[] = (string) $element['id'];
-    }
-    if (!empty($ajax_html_ids)) {
-      $extra_post['ajax_html_ids'] = implode(' ', $ajax_html_ids);
-    }
     $extra_post += $this->getAjaxPageStatePostData();
     // Now serialize all the $extra_post values, and prepend it with an '&'.
     $extra_post = '&' . $this->serializePostValues($extra_post);
diff --git a/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php b/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php
index 5eb13e5..55212bf 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Ajax/MultiFormTest.php
@@ -65,8 +65,8 @@ function testMultiForm() {
     // desired elements.
     $field_name = 'field_ajax_test';
     $field_xpaths = array(
-      'page-node-form' => '//form[@id="page-node-form"]//div[contains(@class, "field-name-field-ajax-test")]',
-      'page-node-form--2' => '//form[@id="page-node-form--2"]//div[contains(@class, "field-name-field-ajax-test")]',
+      'page-node-form' => '//form[starts-with(@id, "page-node-form") and not(contains(@id, "--"))]//div[contains(@class, "field-name-field-ajax-test")]',
+      'page-node-form--2' => '//form[starts-with(@id, "page-node-form") and contains(@id, "--2")]//div[contains(@class, "field-name-field-ajax-test")]',
     );
     $button_name = $field_name . '_add_more';
     $button_value = t('Add another item');
@@ -87,6 +87,7 @@ function testMultiForm() {
     // page update, ensure the same as above.
     foreach ($field_xpaths as $form_html_id => $field_xpath) {
       for ($i = 0; $i < 2; $i++) {
+        // @todo $form_html_id contains old increment suffix, will false-positive.
         $this->drupalPostAjaxForm(NULL, array(), array($button_name => $button_value), 'system/ajax', array(), array(), $form_html_id);
         $this->assert(count($this->xpath($field_xpath . $field_items_xpath_suffix)) == $i+2, 'Found the correct number of field items after an AJAX submission.');
         $this->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, 'Found the "add more" button after an AJAX submission.');
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ViewsFormBase.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ViewsFormBase.php
index 01dceec..460a5e0 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ViewsFormBase.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ViewsFormBase.php
@@ -91,12 +91,6 @@ public function getForm(ViewStorageInterface $view, $display_id, $js) {
     \Drupal::moduleHandler()->loadInclude('views_ui', 'inc', 'admin');
     \Drupal::moduleHandler()->loadInclude('views', 'inc', 'includes/ajax');
 
-    // Reset the cache of IDs. Drupal rather aggressively prevents ID
-    // duplication but this causes it to remember IDs that are no longer even
-    // being used.
-    $seen_ids_init = &drupal_static('drupal_html_id:init');
-    $seen_ids_init = array();
-
     // check to see if this is the top form of the stack. If it is, pop
     // it off; if it isn't, the user clicked somewhere else and the stack is
     // now irrelevant.
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php
index c0be8ee..2416f49 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php
@@ -51,12 +51,6 @@ public function form(array $form, array &$form_state) {
     $form['#suffix'] = '</div>';
     $form['#id'] = 'views-ui-preview-form';
 
-    // Reset the cache of IDs. Drupal rather aggressively prevents ID
-    // duplication but this causes it to remember IDs that are no longer even
-    // being used.
-    $seen_ids_init = &drupal_static('drupal_html_id:init');
-    $seen_ids_init = array();
-
     $form_state['no_cache'] = TRUE;
 
     $form['controls']['#attributes'] = array('class' => array('clearfix'));
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
index 3d49837..61d5f64 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -427,12 +427,6 @@ public function getOverrideValues($form, $form_state) {
    * rather than closing the ajax popup.
    */
   public function addFormToStack($key, $display_id, $type, $id = NULL, $top = FALSE, $rebuild_keys = FALSE) {
-    // Reset the cache of IDs. Drupal rather aggressively prevents ID
-    // duplication but this causes it to remember IDs that are no longer even
-    // being used.
-    $seen_ids_init = &drupal_static('drupal_html_id:init');
-    $seen_ids_init = array();
-
     if (empty($this->stack)) {
       $this->stack = array();
     }
