diff --git a/client/src/entrypoints/admin/preview-panel.js b/client/src/entrypoints/admin/preview-panel.js
index 421a3be9a1..a3944341b6 100644
--- a/client/src/entrypoints/admin/preview-panel.js
+++ b/client/src/entrypoints/admin/preview-panel.js
@@ -101,11 +101,16 @@ function initPreview() {
 
     // Create a new invisible iframe element
     const newIframe = document.createElement('iframe');
+    const url = new URL(previewUrl, window.location.href);
+    if (previewModeSelect) {
+      url.searchParams.set('mode', previewModeSelect.value);
+    }
+    url.searchParams.set('in_preview_panel', 'true');
     newIframe.style.width = 0;
     newIframe.style.height = 0;
     newIframe.style.opacity = 0;
     newIframe.style.position = 'absolute';
-    newIframe.src = iframe.src;
+    newIframe.src = url.toString();
 
     // Put it in the DOM so it loads the page
     iframe.insertAdjacentElement('afterend', newIframe);
@@ -272,10 +277,8 @@ function initPreview() {
 
   const handlePreviewModeChange = (event) => {
     const mode = event.target.value;
-    const url = new URL(iframe.src);
+    const url = new URL(previewUrl, window.location.href);
     url.searchParams.set('mode', mode);
-
-    iframe.src = url.toString();
     url.searchParams.delete('in_preview_panel');
     newTabButton.href = url.toString();
 
diff --git a/wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html b/wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html
index 6b9580a669..7df1f5187c 100644
--- a/wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html
+++ b/wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html
@@ -55,7 +55,7 @@
         </div>
 
         <div class="preview-panel__wrapper">
-            <iframe title="{% trans 'Preview' %}" class="preview-panel__iframe" data-preview-iframe src="{{ preview_url }}?in_preview_panel=true&mode={{ object.default_preview_mode|urlencode }}" aria-describedby="preview-panel-error-banner"></iframe>
+            <iframe loading="lazy" title="{% trans 'Preview' %}" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner"></iframe>
         </div>
     </div>
 </div>
diff --git a/wagtail/admin/tests/pages/test_preview.py b/wagtail/admin/tests/pages/test_preview.py
index 545b626c96..3676ac5c1e 100644
--- a/wagtail/admin/tests/pages/test_preview.py
+++ b/wagtail/admin/tests/pages/test_preview.py
@@ -441,7 +441,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
     def test_show_preview_panel_on_create_with_single_mode(self):
         create_url = self.get_url_on_add("add", self.single)
         preview_url = self.get_url_on_add("preview_on_add", self.single)
-        iframe_url = preview_url + "?in_preview_panel=true&mode="
+        new_tab_url = preview_url + "?mode="
         response = self.client.get(create_url)
 
         self.assertEqual(response.status_code, 200)
@@ -454,9 +454,12 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # Should not show the preview mode selection
         self.assertNotContains(
             response,
@@ -466,7 +469,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
     def test_show_preview_panel_on_create_with_multiple_modes(self):
         create_url = self.get_url_on_add("add", self.multiple)
         preview_url = self.get_url_on_add("preview_on_add", self.multiple)
-        iframe_url = preview_url + "?in_preview_panel=true&mode=alt%231"
+        new_tab_url = preview_url + "?mode=alt%231"
         response = self.client.get(create_url)
 
         self.assertEqual(response.status_code, 200)
@@ -476,12 +479,15 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         self.assertContains(response, 'data-side-panel="preview"')
         self.assertContains(response, 'data-action="%s"' % preview_url)
 
-        # Should show the iframe with the default mode set and correctly quoted
+        # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set and correctly quoted
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # should show the preview mode selection
         self.assertContains(
             response,
@@ -497,7 +503,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
     def test_show_preview_panel_on_edit_with_single_mode(self):
         edit_url = self.get_url_on_edit("edit", self.single)
         preview_url = self.get_url_on_edit("preview_on_edit", self.single)
-        iframe_url = preview_url + "?in_preview_panel=true&mode="
+        new_tab_url = preview_url + "?mode="
         response = self.client.get(edit_url)
 
         self.assertEqual(response.status_code, 200)
@@ -510,9 +516,12 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # Should not show the preview mode selection
         self.assertNotContains(
             response,
@@ -522,7 +531,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
     def test_show_preview_panel_on_edit_with_multiple_modes(self):
         edit_url = self.get_url_on_edit("edit", self.multiple)
         preview_url = self.get_url_on_edit("preview_on_edit", self.multiple)
-        iframe_url = preview_url + "?in_preview_panel=true&mode=alt%231"
+        new_tab_url = preview_url + "?mode=alt%231"
         response = self.client.get(edit_url)
 
         self.assertEqual(response.status_code, 200)
@@ -532,12 +541,15 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         self.assertContains(response, 'data-side-panel="preview"')
         self.assertContains(response, 'data-action="%s"' % preview_url)
 
-        # Should show the iframe with the default mode set and correctly quoted
+        # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set and correctly quoted
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # should show the preview mode selection
         self.assertContains(
             response,
diff --git a/wagtail/snippets/tests/test_preview.py b/wagtail/snippets/tests/test_preview.py
index ae1e58dd2d..ed937fd727 100644
--- a/wagtail/snippets/tests/test_preview.py
+++ b/wagtail/snippets/tests/test_preview.py
@@ -291,7 +291,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
     def test_show_preview_panel_on_create_with_single_mode(self):
         create_url = self.get_url(self.single, "add")
         preview_url = self.get_url(self.single, "preview_on_add")
-        iframe_url = preview_url + "?in_preview_panel=true&mode="
+        new_tab_url = preview_url + "?mode="
         response = self.client.get(create_url)
 
         self.assertEqual(response.status_code, 200)
@@ -304,9 +304,12 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # Should not show the preview mode selection
         self.assertNotContains(
             response,
@@ -316,7 +319,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
     def test_show_preview_panel_on_create_with_multiple_modes(self):
         create_url = self.get_url(self.multiple, "add")
         preview_url = self.get_url(self.multiple, "preview_on_add")
-        iframe_url = preview_url + "?in_preview_panel=true&mode=alt%231"
+        new_tab_url = preview_url + "?mode=alt%231"
         response = self.client.get(create_url)
 
         self.assertEqual(response.status_code, 200)
@@ -326,12 +329,15 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         self.assertContains(response, 'data-side-panel="preview"')
         self.assertContains(response, 'data-action="%s"' % preview_url)
 
-        # Should show the iframe with the default mode set and correctly quoted
+        # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set and correctly quoted
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # should show the preview mode selection
         self.assertContains(
             response,
@@ -349,7 +355,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         preview_url = self.get_url(
             self.single, "preview_on_edit", args=(self.multiple.pk,)
         )
-        iframe_url = preview_url + "?in_preview_panel=true&mode="
+        new_tab_url = preview_url + "?mode="
         response = self.client.get(edit_url)
 
         self.assertEqual(response.status_code, 200)
@@ -362,9 +368,12 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # Should not show the preview mode selection
         self.assertNotContains(
             response,
@@ -376,7 +385,7 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         preview_url = self.get_url(
             self.multiple, "preview_on_edit", args=(self.multiple.pk,)
         )
-        iframe_url = preview_url + "?in_preview_panel=true&mode=alt%231"
+        new_tab_url = preview_url + "?mode=alt%231"
         response = self.client.get(edit_url)
 
         self.assertEqual(response.status_code, 200)
@@ -386,12 +395,15 @@ class TestEnablePreview(WagtailTestUtils, TestCase):
         self.assertContains(response, 'data-side-panel="preview"')
         self.assertContains(response, 'data-action="%s"' % preview_url)
 
-        # Should show the iframe with the default mode set and correctly quoted
+        # Should show the iframe
         self.assertContains(
             response,
-            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
+            '<iframe loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
         )
 
+        # Should show the new tab button with the default mode set and correctly quoted
+        self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
+
         # should show the preview mode selection
         self.assertContains(
             response,