diff --git a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx
index 78a9d17a85f3d..e6aa9421dac85 100644
--- a/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx
+++ b/packages/x-data-grid-pro/src/tests/detailPanel.DataGridPro.test.tsx
@@ -501,6 +501,29 @@ describe(' - Detail panel', () => {
expect(screen.getByTestId(`detail-panel-content`).textContent).to.equal(`${counter}`);
});
+ it("should not render detail panel for the focused row if it's outside of the viewport", function test() {
+ if (isJSDOM) {
+ this.skip(); // Needs layout
+ }
+ render(
+ 50}
+ getDetailPanelContent={() => }
+ rowBufferPx={0}
+ nbRows={20}
+ />,
+ );
+
+ userEvent.mousePress(screen.getAllByRole('button', { name: 'Expand' })[0]);
+
+ const virtualScroller = document.querySelector(`.${gridClasses.virtualScroller}`)!;
+ virtualScroller.scrollTop = 500;
+ act(() => virtualScroller.dispatchEvent(new Event('scroll')));
+
+ const detailPanels = document.querySelectorAll(`.${gridClasses.detailPanel}`);
+ expect(detailPanels.length).to.equal(0);
+ });
+
describe('prop: onDetailPanelsExpandedRowIds', () => {
it('should call when a row is expanded or closed', () => {
const handleDetailPanelsExpandedRowIdsChange = spy();
diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx
index be18719cafd7a..a68ba9bae8e12 100644
--- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx
+++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx
@@ -490,6 +490,10 @@ export const useGridVirtualScroller = () => {
/>,
);
+ if (isNotVisible) {
+ return;
+ }
+
const panel = panels.get(id);
if (panel) {
rows.push(panel);