diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 6f05be09ada3c0f1a66445313fc87317c4925968..7d157a9130d8675cde3e3ca08614319087cddb64 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1269,19 +1269,15 @@ function template_preprocess_html(&$variables) {
   // Create placeholder strings for these keys.
   // @see \Drupal\Core\Render\HtmlResponseSubscriber
   $types = [
-    'styles',
-    'scripts',
-    'scripts_bottom',
-    'head',
+    'styles' => 'css',
+    'scripts' => 'js',
+    'scripts_bottom' => 'js-bottom',
+    'head' => 'head',
   ];
-  $token = Crypt::randomBytesBase64(55);
-  foreach ($types as $type) {
-    $placeholder = SafeMarkup::format('<drupal-html-response-attachment-placeholder type="@type" token="@token"></drupal-html-response-attachment-placeholder>', [
-      '@type' => $type,
-      '@token' => $token,
-    ]);
-    $variables[$type]['#markup'] = $placeholder;
-    $variables[$type]['#attached']['html_response_attachment_placeholders'][$type] = $placeholder;
+  $variables['placeholder_token'] = Crypt::randomBytesBase64(55);
+  foreach ($types as $type => $placeholder_name) {
+    $placeholder = '<' . $placeholder_name . '-placeholder token="' . $variables['placeholder_token'] . '" />';
+    $variables['#attached']['html_response_attachment_placeholders'][$type] = $placeholder;
   }
 }
 
diff --git a/core/modules/system/templates/html.html.twig b/core/modules/system/templates/html.html.twig
index 4985973532ae3b759123896f57454cff9565e61f..9039edc3c1186d2fc44f0f7a1277b33ff4e7e0c8 100644
--- a/core/modules/system/templates/html.html.twig
+++ b/core/modules/system/templates/html.html.twig
@@ -7,9 +7,6 @@
  * - logged_in: A flag indicating if user is logged in.
  * - root_path: The root path of the current page (e.g., node, admin, user).
  * - node_type: The content type for the current node, if the page is a node.
- * - css: A list of CSS files for the current page.
- * - head: Markup for the HEAD element (including meta tags, keyword tags, and
- *   so on).
  * - head_title: List of text elements that make up the head_title variable.
  *   May contain or more of the following:
  *   - title: The title of the page.
@@ -19,11 +16,9 @@
  * - page: The rendered page markup.
  * - page_bottom: Closing rendered markup. This variable should be printed after
  *   'page'.
- * - styles: HTML necessary to import all necessary CSS files in <head>.
- * - scripts: HTML necessary to load JavaScript files and settings in <head>.
- * - scripts_bottom: HTML necessary to load JavaScript files before closing
- *   <body> tag.
  * - db_offline: A flag indicating if the database is offline.
+ * - placeholder_token: The token for generating head, css, js and js-bottom
+ *   placeholders.
  *
  * @see template_preprocess_html()
  *
@@ -33,10 +28,10 @@
 <!DOCTYPE html>
 <html{{ html_attributes }}>
   <head>
-    {{ head }}
+    <head-placeholder token="{{ placeholder_token|raw }}" />
     <title>{{ head_title|safe_join(' | ') }}</title>
-    {{ styles }}
-    {{ scripts }}
+    <css-placeholder token="{{ placeholder_token|raw }}" />
+    <js-placeholder token="{{ placeholder_token|raw }}" />
   </head>
   <body{{ attributes }}>
     <a href="#main-content" class="visually-hidden focusable">
@@ -45,6 +40,6 @@
     {{ page_top }}
     {{ page }}
     {{ page_bottom }}
-    {{ scripts_bottom }}
+    <js-bottom-placeholder token="{{ placeholder_token|raw }}" />
   </body>
 </html>
diff --git a/core/themes/classy/templates/layout/html.html.twig b/core/themes/classy/templates/layout/html.html.twig
index 3911766bb31e2faf2af3d48455f3afeeff04b51e..6c585b2de65cbee51d5ab749ce099613db319b52 100644
--- a/core/themes/classy/templates/layout/html.html.twig
+++ b/core/themes/classy/templates/layout/html.html.twig
@@ -7,9 +7,6 @@
  * - logged_in: A flag indicating if user is logged in.
  * - root_path: The root path of the current page (e.g., node, admin, user).
  * - node_type: The content type for the current node, if the page is a node.
- * - css: A list of CSS files for the current page.
- * - head: Markup for the HEAD element (including meta tags, keyword tags, and
- *   so on).
  * - head_title: List of text elements that make up the head_title variable.
  *   May contain or more of the following:
  *   - title: The title of the page.
@@ -19,11 +16,9 @@
  * - page: The rendered page markup.
  * - page_bottom: Closing rendered markup. This variable should be printed after
  *   'page'.
- * - styles: HTML necessary to import all necessary CSS files in <head>.
- * - scripts: HTML necessary to load JavaScript files and settings in <head>.
- * - scripts_bottom: HTML necessary to load JavaScript files before closing
- *   <body> tag.
  * - db_offline: A flag indicating if the database is offline.
+ * - placeholder_token: The token for generating head, css, js and js-bottom
+ *   placeholders.
  *
  * @see template_preprocess_html()
  */
@@ -39,10 +34,10 @@
 <!DOCTYPE html>
 <html{{ html_attributes }}>
   <head>
-    {{ head }}
+    <head-placeholder token="{{ placeholder_token|raw }}" />
     <title>{{ head_title|safe_join(' | ') }}</title>
-    {{ styles }}
-    {{ scripts }}
+    <css-placeholder token="{{ placeholder_token|raw }}" />
+    <js-placeholder token="{{ placeholder_token|raw }}" />
   </head>
   <body{{ attributes.addClass(body_classes) }}>
     <a href="#main-content" class="visually-hidden focusable skip-link">
@@ -51,6 +46,6 @@
     {{ page_top }}
     {{ page }}
     {{ page_bottom }}
-    {{ scripts_bottom }}
+    <js-bottom-placeholder token="{{ placeholder_token|raw }}" />
   </body>
 </html>