diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 47c99d9..96eb451 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2434,42 +2434,34 @@ function theme_feed_icon($variables) {
 }
 
 /**
- * Returns HTML for a generic HTML tag with attributes.
+ * Prepares variables for HTML tag templates.
  *
- * @param $variables
+ * Default template: html-tag.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
- *   - element: An associative array describing the tag:
- *     - #tag: The tag name to output. Typical tags added to the HTML HEAD:
- *       - meta: To provide meta information, such as a page refresh.
- *       - link: To refer to stylesheets and other contextual information.
- *       - script: To load JavaScript.
- *     - #attributes: (optional) An array of HTML attributes to apply to the
- *       tag.
- *     - #value: (optional) A string containing tag content, such as inline
- *       CSS.
- *     - #value_prefix: (optional) A string to prepend to #value, e.g. a CDATA
- *       wrapper prefix.
- *     - #value_suffix: (optional) A string to append to #value, e.g. a CDATA
- *       wrapper suffix.
+ *   - tag: The tag name to output. Typical tags added to the HTML HEAD:
+ *     - meta: Used to provide meta information, such as a page refresh.
+ *     - link: Used to refer to stylesheets and other contextual information.
+ *     - script: Used for loading JavaScript.
+ *   - attributes: (optional) An array of HTML attributes to apply to the
+ *     tag.
+ *   - value: (optional) A string containing tag content, such as inline CSS.
+ *   - value_prefix: (optional) A string to prepend to #value, e.g. a CDATA
+ *     wrapper prefix.
+ *   - value_suffix: (optional) A string to append to #value, e.g. a CDATA
+ *     wrapper suffix.
  */
-function theme_html_tag($variables) {
-  $element = $variables['element'];
-  $attributes = isset($element['#attributes']) ? new Attribute($element['#attributes']) : '';
-  if (!isset($element['#value'])) {
-    return '<' . $element['#tag'] . $attributes . " />\n";
-  }
-  else {
-    $output = '<' . $element['#tag'] . $attributes . '>';
-    if (isset($element['#value_prefix'])) {
-      $output .= $element['#value_prefix'];
-    }
-    $output .= $element['#value'];
-    if (isset($element['#value_suffix'])) {
-      $output .= $element['#value_suffix'];
+function template_preprocess_html_tag(&$variables) {
+  // Remove default 'html-tag' class from attributes, but leave other classes.
+  // @todo: Remove this hack once http://drupal.org/node/1938430 lands.
+  if (!empty($variables['attributes']['class'])) {
+    $variables['attributes']['class'] = array_diff($variables['attributes']['class'], array('html-tag'));
+    if (empty($variables['attributes']['class'])) {
+      unset($variables['attributes']['class']);
     }
-    $output .= '</' . $element['#tag'] . ">\n";
-    return $output;
   }
+  $variables['attributes'] = new Attribute($variables['attributes']);
 }
 
 /**
@@ -3208,7 +3200,8 @@ function drupal_common_theme() {
       'variables' => array('size' => 1),
     ),
     'html_tag' => array(
-      'render element' => 'element',
+      'variables' => array('tag' => NULL, 'value' => NULL, 'attributes' => array(), 'value_prefix' => NULL, 'value_suffix' => NULL),
+      'template' => 'html-tag',
     ),
     // From theme.maintenance.inc.
     'maintenance_page' => array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/HtmlTagTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/HtmlTagTest.php
new file mode 100644
index 0000000..c3dc972
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/HtmlTagTest.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Theme\HtmlTagTest.
+ */
+
+namespace Drupal\system\Tests\Theme;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests HTML tag output.
+ */
+class HtmlTagTest extends WebTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'HTML tag output',
+      'description' => "Tests output of '#theme' => 'html_tag'.",
+      'group' => 'Theme',
+    );
+  }
+
+  /**
+   * Tests the output of '#theme' => 'html_tag'.
+   */
+  function testThemeHtmlTag() {
+    // Test auto-closure meta tag generation.
+    $tag = array('#theme' => 'html_tag', '#tag' => 'meta', '#attributes' => array('name' => 'description', 'content' => 'Drupal test'));
+    $this->assertEqual('<meta name="description" content="Drupal test" />' . "\n", drupal_render($tag), 'Test auto-closure meta tag generation.');
+
+    // Test title tag generation.
+    $tag = array('#theme' => 'html_tag', '#tag' => 'title', '#value' => 'title test');
+    $this->assertEqual('<title>title test</title>' . "\n", drupal_render($tag), 'Test title tag generation.');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/HtmlTagUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/HtmlTagUnitTest.php
deleted file mode 100644
index b8c6ffb..0000000
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/HtmlTagUnitTest.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Theme\HtmlTagUnitTest.
- */
-
-namespace Drupal\system\Tests\Theme;
-
-use Drupal\simpletest\UnitTestBase;
-
-/**
- * Unit tests for theme_html_tag().
- */
-class HtmlTagUnitTest extends UnitTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => 'Theme HTML Tag',
-      'description' => 'Tests theme_html_tag() built-in theme functions.',
-      'group' => 'Theme',
-    );
-  }
-
-  /**
-   * Test function theme_html_tag()
-   */
-  function testThemeHtmlTag() {
-    // Test auto-closure meta tag generation
-    $tag['element'] = array('#tag' => 'meta', '#attributes' => array('name' => 'description', 'content' => 'Drupal test'));
-    $this->assertEqual('<meta name="description" content="Drupal test" />'."\n", theme_html_tag($tag), 'Test auto-closure meta tag generation.');
-
-    // Test title tag generation
-    $tag['element'] = array('#tag' => 'title', '#value' => 'title test');
-    $this->assertEqual('<title>title test</title>'."\n", theme_html_tag($tag), 'Test title tag generation.');
-  }
-}
diff --git a/core/modules/system/templates/html-tag.html.twig b/core/modules/system/templates/html-tag.html.twig
new file mode 100644
index 0000000..83a876c
--- /dev/null
+++ b/core/modules/system/templates/html-tag.html.twig
@@ -0,0 +1,40 @@
+{#
+/**
+ * Default theme implementation for a generic HTML tag with attributes.
+ *
+ * Available variables:
+ * - tag: The tag name to output. Typical tags added to the HTML <head>:
+ *   - meta: Used to provide meta information, such as a page refresh.
+ *   - link: Used to refer to stylesheets and other contextual information.
+ *   - script: Used for loading JavaScript.
+ * - attributes: (optional) Remaining HTML attributes to apply to the tag.
+ * - value: (optional) The tag content, such as inline CSS.
+ * - value_prefix: (optional) Prepend this to 'value', e.g. a CDATA wrapper
+ *   prefix.
+ * - value_suffix: (optional) Append this to 'value', e.g. a CDATA wrapper
+ *   suffix.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_html_tag()
+ *
+ * @ingroup themeable
+ */
+ @todo Delete this file once http://drupal.org/node/1825090 is resolved.
+#}
+{#
+  We use 'is not null' here because <script> always needs a closing tag, and
+  'value' is set to an empty string for <script> tags with only a src value.
+#}
+{% if value is not null -%}
+  <{{ tag }}{{ attributes }}>
+    {%- if value_prefix -%}
+      {{- value_prefix -}}
+    {%- endif -%}
+    {{- value -}}
+    {%- if value_suffix -%}
+      {{- value_suffix -}}
+    {%- endif -%}
+  </{{ tag }}>
+{% else -%}
+  <{{ tag }}{{ attributes }} />
+{% endif %}
