diff --git a/core/modules/big_pipe/big_pipe.module b/core/modules/big_pipe/big_pipe.module
index 18bbbb2..df27c06 100644
--- a/core/modules/big_pipe/big_pipe.module
+++ b/core/modules/big_pipe/big_pipe.module
@@ -7,6 +7,7 @@
 
 use Drupal\big_pipe\Render\Placeholder\BigPipeStrategy;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Component\Utility\Html;
 use Drupal\Core\Url;
 
 /**
@@ -77,3 +78,43 @@ function big_pipe_page_attachments(array &$page) {
     }
   }
 }
+
+/**
+ * Implements hook_theme().
+ */
+function big_pipe_theme() {
+  return array(
+    'big_pipe_js_placeholder' => array(
+      'render element' => 'elements',
+    ),
+  );
+}
+
+/**
+ * Implements hook_theme_suggestions_HOOK().
+ */
+function big_pipe_theme_suggestions_big_pipe_js_placeholder(array $variables) {
+  $placeholder = reset($variables['elements']['#attached']['big_pipe_placeholders']);
+  $base_suggestion = $variables['theme_hook_original'];
+  $suggestions = [];
+  if (!empty($placeholder['#lazy_builder'])) {
+    $callback = $placeholder['#lazy_builder'][0];
+    $suggestions[] = $base_suggestion = $base_suggestion . '__' . strtolower(str_replace(['\\', '::', ':', '.'], '_', $callback));
+  }
+  if (!empty($placeholder['#cache']['keys'])) {
+    $base_suggestion = $variables['theme_hook_original'];
+    foreach ($placeholder['#cache']['keys'] as $key) {
+      $suggestions[] = $base_suggestion = $base_suggestion . '__' . $key;
+    }
+  }
+  return $suggestions;
+}
+
+/**
+ * Prepares variables for Big Pipe placeholder templates.
+ *
+ * Default template: big-pipe-js-placeholder.html.twig.
+ */
+function template_preprocess_big_pipe_js_placeholder(&$variables) {
+  $variables['attributes']['data-big-pipe-placeholder-id'] = $variables['elements']['#big_pipe_js_selector'];
+}
diff --git a/core/modules/big_pipe/src/Render/BigPipe.php b/core/modules/big_pipe/src/Render/BigPipe.php
index 3e67737..044ef13 100644
--- a/core/modules/big_pipe/src/Render/BigPipe.php
+++ b/core/modules/big_pipe/src/Render/BigPipe.php
@@ -511,14 +511,13 @@ protected function renderPlaceholder($placeholder, array $placeholder_render_arr
    *   Values are the BigPipe placeholder IDs.
    */
   protected function getPlaceholderOrder($html) {
-    $fragments = explode('<div data-big-pipe-placeholder-id="', $html);
-    array_shift($fragments);
+    $dom = Html::load($html);
+    $xpath = new \DOMXPath($dom);
+    $elements = $xpath->query('//*[@data-big-pipe-placeholder-id]');
     $order = [];
 
-    foreach ($fragments as $fragment) {
-      $t = explode('"></div>', $fragment, 2);
-      $placeholder = $t[0];
-      $order[] = $placeholder;
+    foreach ($elements as $element) {
+      $order[] = Html::escape($element->getAttribute('data-big-pipe-placeholder-id'));
     }
 
     return $order;
diff --git a/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php b/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php
index 91ad604..30ad9db 100644
--- a/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php
+++ b/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php
@@ -183,7 +183,8 @@ protected static function createBigPipeJsPlaceholder($original_placeholder, arra
     $big_pipe_placeholder_id = static::generateBigPipePlaceholderId($original_placeholder, $placeholder_render_array);
 
     return [
-      '#markup' => '<div data-big-pipe-placeholder-id="' . Html::escape($big_pipe_placeholder_id) . '"></div>',
+      '#theme' => 'big_pipe_js_placeholder',
+      '#big_pipe_js_selector' => $big_pipe_placeholder_id,
       '#cache' => [
         'max-age' => 0,
         'contexts' => [
diff --git a/core/modules/big_pipe/templates/big-pipe-js-placeholder.html.twig b/core/modules/big_pipe/templates/big-pipe-js-placeholder.html.twig
new file mode 100644
index 0000000..6920950
--- /dev/null
+++ b/core/modules/big_pipe/templates/big-pipe-js-placeholder.html.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * Default theme implementation to display a Big Pipe JS placeholder.
+ *
+ * Available variables:
+ * - attributes: array of HTML attributes populated by modules, intended to
+ *   be added to the main container tag of this template.
+ *   - data-big-pipe-selector: The selector used by Big Pipe to replace this
+ *     element with the lazy loaded content.
+ *
+ * @see template_preprocess_big_pipe_js_placeholder()
+ *
+ * @ingroup themeable
+ */
+#}
+<div{{ attributes }}></div>
