diff --git a/Tests/LibWeb/Text/expected/CSSOMView/getClientRects-in-detached-document.txt b/Tests/LibWeb/Text/expected/CSSOMView/getClientRects-in-detached-document.txt
new file mode 100644
index 0000000000..cbd504d097
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/CSSOMView/getClientRects-in-detached-document.txt
@@ -0,0 +1,3 @@
+[object CSSStyleDeclaration]
+[object DOMRectList]
+PASS (didn't crash)
diff --git a/Tests/LibWeb/Text/input/CSSOMView/getClientRects-in-detached-document.html b/Tests/LibWeb/Text/input/CSSOMView/getClientRects-in-detached-document.html
new file mode 100644
index 0000000000..6c139aa075
--- /dev/null
+++ b/Tests/LibWeb/Text/input/CSSOMView/getClientRects-in-detached-document.html
@@ -0,0 +1,16 @@
+
+
diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp
index f9d034dea1..c453692eae 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Element.cpp
@@ -949,7 +949,9 @@ JS::NonnullGCPtr Element::get_bounding_client_rect() const
// https://drafts.csswg.org/cssom-view/#dom-element-getclientrects
JS::NonnullGCPtr Element::get_client_rects() const
{
- Vector> rects;
+ auto navigable = document().navigable();
+ if (!navigable)
+ return Geometry::DOMRectList::create(realm(), {});
// NOTE: Ensure that layout is up-to-date before looking at metrics.
const_cast(document()).update_layout();
@@ -957,7 +959,7 @@ JS::NonnullGCPtr Element::get_client_rects() const
// 1. If the element on which it was invoked does not have an associated layout box return an empty DOMRectList
// object and stop this algorithm.
if (!layout_node())
- return Geometry::DOMRectList::create(realm(), move(rects));
+ return Geometry::DOMRectList::create(realm(), {});
// FIXME: 2. If the element has an associated SVG layout box return a DOMRectList object containing a single
// DOMRect object that describes the bounding box of the element as defined by the SVG specification,
@@ -970,9 +972,6 @@ JS::NonnullGCPtr Element::get_client_rects() const
// or inline-table include both the table box and the caption box, if any, but not the anonymous container box.
// FIXME: - Replace each anonymous block box with its child box(es) and repeat this until no anonymous block boxes
// are left in the final list.
- const_cast(document()).update_layout();
- auto navigable = document().navigable();
- VERIFY(navigable);
auto viewport_offset = navigable->viewport_scroll_offset();
// NOTE: Make sure CSS transforms are resolved before it is used to calculate the rect position.
@@ -982,6 +981,7 @@ JS::NonnullGCPtr Element::get_client_rects() const
CSSPixelPoint scroll_offset;
auto const* paintable = this->paintable();
+ Vector> rects;
if (auto const* paintable_box = this->paintable_box()) {
transform = Gfx::extract_2d_affine_transform(paintable_box->transform());
for (auto const* containing_block = paintable->containing_block(); !containing_block->is_viewport(); containing_block = containing_block->containing_block()) {