diff --git a/core/includes/common.inc b/core/includes/common.inc
index 65aef09..832bedf 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -13,6 +13,7 @@
 use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
 use Drupal\Component\Utility\Bytes;
 use Drupal\Component\Utility\Crypt;
+use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\Number;
 use Drupal\Component\Utility\SortArray;
 use Drupal\Component\Utility\String;
@@ -1426,25 +1427,12 @@ function drupal_delete_file_if_stale($uri) {
  *
  * @return
  *   The cleaned identifier.
+ *
+ * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ *   Use \Drupal\Component\Utility\Html::cleanCssIdentifier()
  */
 function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_' => '-', '__' => '__', '/' => '-', '[' => '-', ']' => '')) {
-  // By default, we filter using Drupal's coding standards.
-  $identifier = strtr($identifier, $filter);
-
-  // Valid characters in a CSS identifier are:
-  // - the hyphen (U+002D)
-  // - a-z (U+0030 - U+0039)
-  // - A-Z (U+0041 - U+005A)
-  // - the underscore (U+005F)
-  // - 0-9 (U+0061 - U+007A)
-  // - ISO 10646 characters U+00A1 and higher
-  // We strip out any character not in the above list.
-  $identifier = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', $identifier);
-
-  // Identifiers cannot start with a digit, two hyphens, or a hyphen followed by a digit.
-  $identifier = preg_replace(array('/^[0-9]/', '/^(-[0-9])|^(--)/'), array('_', '__') , $identifier);
-
-  return $identifier;
+  return Html::cleanCssIdentifier($identifier, $filter);
 }
 
 /**
@@ -1458,16 +1446,12 @@ function drupal_clean_css_identifier($identifier, $filter = array(' ' => '-', '_
  *
  * @return
  *   The cleaned class name.
+ *
+ * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ *   Use \Drupal\Component\Utility\Html::getClass()
  */
 function drupal_html_class($class) {
-  // The output of this function will never change, so this uses a normal
-  // static instead of drupal_static().
-  static $classes = array();
-
-  if (!isset($classes[$class])) {
-    $classes[$class] = drupal_clean_css_identifier(drupal_strtolower($class));
-  }
-  return $classes[$class];
+  return Html::getClass($class);
 }
 
 /**
@@ -1496,66 +1480,12 @@ function drupal_html_class($class) {
  *
  * @return
  *   The cleaned ID.
+ *
+ * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ *   Use \Drupal\Component\Utility\Html::getUniqueId()
  */
 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;
-        }
-      }
-    }
-  }
-  $seen_ids = &drupal_static(__FUNCTION__, $seen_ids_init);
-
-  $id = drupal_clean_id_identifier($id);
-  // 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
-  // return unique IDs and also helps us re-create the $seen_ids array during
-  // Ajax requests.
-  if (isset($seen_ids[$id])) {
-    $id = $id . '--' . ++$seen_ids[$id];
-  }
-  else {
-    $seen_ids[$id] = 1;
-  }
-
-  return $id;
+  return Html::getUniqueId($id);
 }
 
 /**
@@ -1571,21 +1501,12 @@ function drupal_html_id($id) {
  *   The cleaned ID.
  *
  * @see drupal_html_id()
+ *
+ * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
+ *   Use \Drupal\Component\Utility\Html::getId()
  */
 function drupal_clean_id_identifier($id) {
-  $id = strtr(drupal_strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
-
-  // As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can
-  // only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"),
-  // colons (":"), and periods ("."). We strip out any character not in that
-  // list. Note that the CSS spec doesn't allow colons or periods in identifiers
-  // (http://www.w3.org/TR/CSS21/syndata.html#characters), so we strip those two
-  // characters as well.
-  $id = preg_replace('/[^A-Za-z0-9\-_]/', '', $id);
-
-  // Removing multiple consecutive hyphens.
-  $id = preg_replace('/\-+/', '-', $id);
-  return $id;
+  return Html::getId($id);
 }
 
 /**
diff --git a/core/lib/Drupal/Component/Utility/Html.php b/core/lib/Drupal/Component/Utility/Html.php
index 2b5455f..04ce629 100644
--- a/core/lib/Drupal/Component/Utility/Html.php
+++ b/core/lib/Drupal/Component/Utility/Html.php
@@ -15,6 +15,212 @@
 class Html {
 
   /**
+   * An array of previously cleaned HTML classes.
+   *
+   * @var array
+   */
+  protected static $classes = array();
+
+  /**
+   * An array of the initial IDs used in one request.
+   *
+   * @var array
+   */
+  protected static $seenIdsInit;
+
+  /**
+   * An array of IDs, including incremented versions when an ID is duplicated.
+   * @var array
+   */
+  protected static $seenIds;
+
+  /**
+   * Prepares a string for use as a valid class name.
+   *
+   * Do not pass one string containing multiple classes as they will be
+   * incorrectly concatenated with dashes, i.e. "one two" will become "one-two".
+   *
+   * @param string $class
+   *   The class name to clean.
+   *
+   * @return string
+   *   The cleaned class name.
+   */
+  public static function getClass($class) {
+    if (!isset(static::$classes[$class])) {
+      static::$classes[$class] = static::cleanCssIdentifier(Unicode::strtolower($class));
+    }
+    return static::$classes[$class];
+  }
+
+  /**
+   * Prepares a string for use as a CSS identifier (element, class, or ID name).
+   *
+   * http://www.w3.org/TR/CSS21/syndata.html#characters shows the syntax for
+   * valid CSS identifiers (including element names, classes, and IDs in
+   * selectors.)
+   *
+   * @param string $identifier
+   *   The identifier to clean.
+   * @param array $filter
+   *   An array of string replacements to use on the identifier.
+   *
+   * @return string
+   *   The cleaned identifier.
+   */
+  public static function cleanCssIdentifier($identifier, array $filter = array(
+    ' ' => '-',
+    '_' => '-',
+    '__' => '__',
+    '/' => '-',
+    '[' => '-',
+    ']' => ''
+  )) {
+    $identifier = strtr($identifier, $filter);
+    // Valid characters in a CSS identifier are:
+    // - the hyphen (U+002D)
+    // - a-z (U+0030 - U+0039)
+    // - A-Z (U+0041 - U+005A)
+    // - the underscore (U+005F)
+    // - 0-9 (U+0061 - U+007A)
+    // - ISO 10646 characters U+00A1 and higher
+    // We strip out any character not in the above list.
+    $identifier = preg_replace('/[^\x{002D}\x{0030}-\x{0039}\x{0041}-\x{005A}\x{005F}\x{0061}-\x{007A}\x{00A1}-\x{FFFF}]/u', '', $identifier);
+    // Identifiers cannot start with a digit, two hyphens, or a hyphen followed by a digit.
+    $identifier = preg_replace(array(
+      '/^[0-9]/',
+      '/^(-[0-9])|^(--)/'
+    ), array('_', '__'), $identifier);
+    return $identifier;
+  }
+
+  /**
+   * Prepares a string for use as a valid HTML ID and guarantees uniqueness.
+   *
+   * This function ensures that each passed HTML ID value only exists once on
+   * the page. By tracking the already returned ids, this function enables
+   * forms, blocks, and other content to be output multiple times on the same
+   * page, without breaking (X)HTML validation.
+   *
+   * For already existing IDs, a counter is appended to the ID string.
+   * Therefore, JavaScript and CSS code should not rely on any value that was
+   * generated by this function and instead should rely on manually added CSS
+   * classes or similarly reliable constructs.
+   *
+   * Two consecutive hyphens separate the counter from the original ID. To
+   * manage uniqueness across multiple Ajax requests on the same page, Ajax
+   * requests POST an array of all IDs currently present on the page, which are
+   * used to prime this function's cache upon first invocation.
+   *
+   * To allow reverse-parsing of IDs submitted via Ajax, any multiple
+   * consecutive hyphens in the originally passed $id are replaced with a
+   * single hyphen.
+   *
+   * @param string $id
+   *   The ID to clean.
+   *
+   * @return string
+   *   The cleaned ID.
+   */
+  public static function getUniqueId($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.
+    if (!isset(static::$seenIdsInit)) {
+      // 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($_POST['ajax_html_ids'])) {
+        static::$seenIdsInit = 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(' ', $_POST['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(static::$seenIdsInit[$seen_id]) || ($i > static::$seenIdsInit[$seen_id])) {
+            static::$seenIdsInit[$seen_id] = $i;
+          }
+        }
+      }
+    }
+    if (!isset(static::$seenIds)) {
+      static::$seenIds = static::$seenIdsInit;
+    }
+
+    $id = static::getId($id);
+
+    // 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
+    // return unique IDs and also helps us re-create the $seen_ids array during
+    // Ajax requests.
+    if (isset(static::$seenIds[$id])) {
+      $id = $id . '--' . ++static::$seenIds[$id];
+    }
+    else {
+      static::$seenIds[$id] = 1;
+    }
+    return $id;
+  }
+
+  /**
+   * Prepares a string for use as a valid HTML ID.
+   *
+   * Only use this function when you want to intentionally skip the uniqueness
+   * guarantee of self::getUniqueId().
+   *
+   * @param string $id
+   *   The ID to clean.
+   *
+   * @return string
+   *   The cleaned ID.
+   *
+   * @see self::getUniqueId()
+   */
+  public static function getId($id) {
+    $id = strtr(Unicode::strtolower($id), array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
+
+    // As defined in http://www.w3.org/TR/html4/types.html#type-name, HTML IDs can
+    // only contain letters, digits ([0-9]), hyphens ("-"), underscores ("_"),
+    // colons (":"), and periods ("."). We strip out any character not in that
+    // list. Note that the CSS spec doesn't allow colons or periods in identifiers
+    // (http://www.w3.org/TR/CSS21/syndata.html#characters), so we strip those two
+    // characters as well.
+    $id = preg_replace('/[^A-Za-z0-9\-_]/', '', $id);
+
+    // Removing multiple consecutive hyphens.
+    $id = preg_replace('/\-+/', '-', $id);
+    return $id;
+  }
+
+  /**
+   * Resets the list of seen IDs.
+   */
+  public static function resetSeenIds() {
+    static::$seenIds = NULL;
+  }
+
+  /**
    * Normalizes an HTML snippet.
    *
    * This function is essentially \DOMDocument::normalizeDocument(), but
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index d3bedc1..861595d 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Form;
 
 use Drupal\Component\Utility\Crypt;
+use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Access\CsrfTokenGenerator;
@@ -482,10 +483,10 @@ public function retrieveForm($form_id, &$form_state) {
     // Assign a default CSS class name based on $form_id.
     // This happens here and not in self::prepareForm() in order to allow the
     // form constructor function to override or remove the default class.
-    $form['#attributes']['class'][] = $this->drupalHtmlClass($form_id);
+    $form['#attributes']['class'][] = Html::getClass($form_id);
     // Same for the base form ID, if any.
     if (isset($form_state['build_info']['base_form_id'])) {
-      $form['#attributes']['class'][] = $this->drupalHtmlClass($form_state['build_info']['base_form_id']);
+      $form['#attributes']['class'][] = Html::getClass($form_state['build_info']['base_form_id']);
     }
 
     // We need to pass $form_state by reference in order for forms to modify it,
@@ -555,7 +556,7 @@ public function processForm($form_id, &$form, &$form_state) {
       // element IDs needlessly.
       if (!$this->getAnyErrors()) {
         // In case of errors, do not break HTML IDs of other forms.
-        $this->drupalStaticReset('drupal_html_id');
+        Html::resetSeenIds();
       }
 
       if (!$form_state['rebuild'] && !$this->formValidator->getAnyErrors()) {
@@ -657,7 +658,7 @@ public function prepareForm($form_id, &$form, &$form_state) {
       else {
         $form['#token'] = $form_id;
         $form['form_token'] = array(
-          '#id' => $this->drupalHtmlId('edit-' . $form_id . '-form-token'),
+          '#id' => Html::getUniqueId('edit-' . $form_id . '-form-token'),
           '#type' => 'token',
           '#default_value' => $this->csrfToken->get($form['#token']),
           // Form processing and validation requires this value, so ensure the
@@ -672,7 +673,7 @@ public function prepareForm($form_id, &$form, &$form_state) {
       $form['form_id'] = array(
         '#type' => 'hidden',
         '#value' => $form_id,
-        '#id' => $this->drupalHtmlId("edit-$form_id"),
+        '#id' => Html::getUniqueId("edit-$form_id"),
         // Form processing and validation requires this value, so ensure the
         // submitted form value appears literally, regardless of custom #tree
         // and #parents being set elsewhere.
@@ -680,7 +681,7 @@ public function prepareForm($form_id, &$form, &$form_state) {
       );
     }
     if (!isset($form['#id'])) {
-      $form['#id'] = $this->drupalHtmlId($form_id);
+      $form['#id'] = Html::getUniqueId($form_id);
     }
 
     $form += $this->getElementInfo('form');
@@ -869,7 +870,7 @@ public function doBuildForm($form_id, &$element, &$form_state) {
     }
 
     if (!isset($element['#id'])) {
-      $element['#id'] = $this->drupalHtmlId('edit-' . implode('-', $element['#parents']));
+      $element['#id'] = Html::getUniqueId('edit-' . implode('-', $element['#parents']));
     }
 
     // Add the aria-describedby attribute to associate the form control with its
@@ -1248,31 +1249,6 @@ protected function getElementInfo($type) {
   }
 
   /**
-   * Wraps drupal_html_class().
-   *
-   * @return string
-   */
-  protected function drupalHtmlClass($class) {
-    return drupal_html_class($class);
-  }
-
-  /**
-   * Wraps drupal_html_id().
-   *
-   * @return string
-   */
-  protected function drupalHtmlId($id) {
-    return drupal_html_id($id);
-  }
-
-  /**
-   * Wraps drupal_static_reset().
-   */
-  protected function drupalStaticReset($name = NULL) {
-    drupal_static_reset($name);
-  }
-
-  /**
    * Gets the current active user.
    *
    * @return \Drupal\Core\Session\AccountInterface
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockViewBuilderTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockViewBuilderTest.php
index a6571cb..8f67e95 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockViewBuilderTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockViewBuilderTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\block\Tests;
 
+use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\UrlCacheContext;
 use Drupal\simpletest\DrupalUnitTestBase;
@@ -103,7 +104,7 @@ public function testBasicRendering() {
     $this->assertEqual(drupal_render($output), $expected_output);
 
     // Reset the HTML IDs so that the next render is not affected.
-    drupal_static_reset('drupal_html_id');
+    Html::resetSeenIds();
 
     // Test the rendering of a block with a given title.
     $entity = $this->controller->create(array(
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index a120883..1324f81 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -1809,6 +1809,7 @@ protected function drupalPostAjaxForm($path, $edit, $triggering_element, $ajax_p
     $return = Json::decode($this->drupalPostForm(NULL, $edit, array('path' => $ajax_path, 'triggering_element' => $triggering_element), $options, $headers, $form_html_id, $extra_post));
 
     // Change the page content by applying the returned commands.
+    debug($ajax_settings);
     if (!empty($ajax_settings) && !empty($return)) {
       $this->drupalProcessAjaxResponse($content, $return, $ajax_settings, $drupal_settings);
     }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/HtmlIdentifierUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/HtmlIdentifierUnitTest.php
deleted file mode 100644
index ec9bbb4..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Common/HtmlIdentifierUnitTest.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Common\HtmlIdentifierUnitTest.
- */
-
-namespace Drupal\system\Tests\Common;
-
-use Drupal\simpletest\UnitTestBase;
-use Symfony\Component\HttpFoundation\Request;
-
-/**
- * Tests cleaning HTML identifiers.
- */
-class HtmlIdentifierUnitTest extends UnitTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => 'HTML identifiers',
-      'description' => 'Test the functions drupal_html_class(), drupal_html_id() and drupal_clean_css_identifier() for expected behavior',
-      'group' => 'Common',
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setUp() {
-    parent::setUp();
-
-    $container = \Drupal::getContainer();
-    $request = new Request();
-    $container->set('request', $request);
-    \Drupal::setContainer($container);
-  }
-
-  /**
-   * Tests that drupal_clean_css_identifier() cleans the identifier properly.
-   */
-  function testDrupalCleanCSSIdentifier() {
-    // Verify that no valid ASCII characters are stripped from the identifier.
-    $identifier = 'abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789';
-    $this->assertIdentical(drupal_clean_css_identifier($identifier, array()), $identifier, 'Verify valid ASCII characters pass through.');
-
-    // Verify that valid UTF-8 characters are not stripped from the identifier.
-    $identifier = '¡¢£¤¥';
-    $this->assertIdentical(drupal_clean_css_identifier($identifier, array()), $identifier, 'Verify valid UTF-8 characters pass through.');
-
-    // Verify that invalid characters (including non-breaking space) are stripped from the identifier.
-    $this->assertIdentical(drupal_clean_css_identifier('invalid !"#$%&\'()*+,./:;<=>?@[\\]^`{|}~ identifier', array()), 'invalididentifier', 'Strip invalid characters.');
-
-    // Verify that double underscores are not stripped from the identifier.
-    $identifier = 'css__identifier__with__double__underscores';
-    $this->assertIdentical(drupal_clean_css_identifier($identifier), $identifier, 'Verify double underscores pass through.');
-
-    // Verify that an identifier starting with a digit is replaced.
-    $this->assertIdentical(drupal_clean_css_identifier('1cssidentifier', array()), '_cssidentifier', 'Verify identifier starting with a digit is replaced.');
-
-    // Verify that an identifier starting with a hyphen followed by a digit is
-    // replaced.
-    $this->assertIdentical(drupal_clean_css_identifier('-1cssidentifier', array()), '__cssidentifier', 'Verify identifier starting with a hyphen followed by a digit is replaced.');
-
-    // Verify that an identifier starting with two hyphens is replaced.
-    $this->assertIdentical(drupal_clean_css_identifier('--cssidentifier', array()), '__cssidentifier', 'Verify identifier starting with two hyphens is replaced.');
-  }
-
-  /**
-   * Tests that drupal_html_class() cleans the class name properly.
-   */
-  function testDrupalHTMLClass() {
-    // Verify Drupal coding standards are enforced.
-    $this->assertIdentical(drupal_html_class('CLASS NAME_[Ü]'), 'class-name--ü', 'Enforce Drupal coding standards.');
-  }
-
-  /**
-   * Tests that drupal_html_id() cleans the ID properly.
-   */
-  function testDrupalHTMLId() {
-    // Verify that letters, digits, and hyphens are not stripped from the ID.
-    $id = 'abcdefghijklmnopqrstuvwxyz-0123456789';
-    $this->assertIdentical(drupal_html_id($id), $id, 'Verify valid characters pass through.');
-
-    // Verify that invalid characters are stripped from the ID.
-    $this->assertIdentical(drupal_html_id('invalid,./:@\\^`{Üidentifier'), 'invalididentifier', 'Strip invalid characters.');
-
-    // Verify Drupal coding standards are enforced.
-    $this->assertIdentical(drupal_html_id('ID NAME_[1]'), 'id-name-1', 'Enforce Drupal coding standards.');
-
-    // Reset the static cache so we can ensure the unique id count is at zero.
-    drupal_static_reset('drupal_html_id');
-
-    // Clean up IDs with invalid starting characters.
-    $this->assertIdentical(drupal_html_id('test-unique-id'), 'test-unique-id', 'Test the uniqueness of IDs #1.');
-    $this->assertIdentical(drupal_html_id('test-unique-id'), 'test-unique-id--2', 'Test the uniqueness of IDs #2.');
-    $this->assertIdentical(drupal_html_id('test-unique-id'), 'test-unique-id--3', 'Test the uniqueness of IDs #3.');
-  }
-}
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 c6cb25f..261f805 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
@@ -7,6 +7,7 @@
 
 namespace Drupal\views_ui\Form\Ajax;
 
+use Drupal\Component\Utility\Html;
 use Drupal\Core\Form\FormBase;
 use Drupal\views\ViewStorageInterface;
 use Drupal\views\Ajax;
@@ -94,8 +95,7 @@ public function getForm(ViewStorageInterface $view, $display_id, $js) {
     // 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();
+    Html::resetSeenIds();
 
     // 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
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/RowUITest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/RowUITest.php
index cc8c5c3..11710f0 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/RowUITest.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/RowUITest.php
@@ -68,7 +68,7 @@ public function testRowUI() {
 
     // Change the row plugin to fields using ajax.
     $this->drupalPostAjaxForm($row_plugin_url, array('row[type]' => 'fields'), array('op' => 'Apply'), str_replace('/nojs/', '/ajax/', $row_plugin_url));
-    $this->drupalPostAjaxForm(NULL, array(), array('op' => 'Apply'));
+    $this->drupalPostAjaxForm(NULL, array(), array('op' => 'Apply'), str_replace('/nojs/', '/ajax/', $row_plugin_url));
     $this->assertResponse(200);
     $this->assertFieldByName('row[type]', 'fields', 'Make sure that the fields got saved as used row plugin.');
   }
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 52d99b2..4c98efb 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views_ui;
 
+use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Timer;
 use Drupal\Component\Utility\Xss;
@@ -431,8 +432,7 @@ public function addFormToStack($key, $display_id, $type, $id = NULL, $top = FALS
     // 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();
+    Html::resetSeenIds();
 
     if (empty($this->stack)) {
       $this->stack = array();
diff --git a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
index 640ce98..bea43ac 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormTestBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Form {
 
+use Drupal\Component\Utility\Html;
 use Drupal\Core\Form\FormBuilder;
 use Drupal\Core\Form\FormInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -178,7 +179,7 @@ public function setUp() {
    * {@inheritdoc}
    */
   protected function tearDown() {
-    $this->formBuilder->drupalStaticReset();
+    Html::resetSeenIds();
   }
 
   /**
@@ -308,33 +309,6 @@ protected function getElementInfo($type) {
     return $types[$type];
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function drupalHtmlClass($class) {
-    return $class;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function drupalHtmlId($id) {
-    if (isset(static::$seenIds[$id])) {
-      $id = $id . '--' . ++static::$seenIds[$id];
-    }
-    else {
-      static::$seenIds[$id] = 1;
-    }
-    return $id;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function drupalStaticReset($name = NULL) {
-    static::$seenIds = array();
-  }
-
 }
 
 }
