diff --git a/frontend/src/metabase/App.tsx b/frontend/src/metabase/App.tsx
index 7425d48539b5309c9f7ea87885007cc6bd3fd3e7..1ab0adfbb81e7cfc0fc5e4fb65d800ebee008e60 100644
--- a/frontend/src/metabase/App.tsx
+++ b/frontend/src/metabase/App.tsx
@@ -1,4 +1,4 @@
-import React, { ErrorInfo, ReactNode, useState } from "react";
+import React, { ErrorInfo, ReactNode, useRef, useState } from "react";
 import { connect } from "react-redux";
 import { Location } from "history";
 
@@ -25,6 +25,7 @@ import { initializeIframeResizer } from "metabase/lib/dom";
 import AppBar from "metabase/nav/containers/AppBar";
 import Navbar from "metabase/nav/containers/Navbar";
 import StatusListing from "metabase/status/containers/StatusListing";
+import { ContentViewportContext } from "metabase/core/context/ContentViewportContext";
 
 import { AppErrorDescriptor, State } from "metabase-types/store";
 
@@ -89,6 +90,7 @@ function App({
   isNavBarVisible,
   children,
 }: AppProps) {
+  const [viewportElement, setViewportElement] = useState<HTMLElement | null>();
   const [errorInfo, setErrorInfo] = useState<ErrorInfo | null>(null);
 
   useOnMount(() => {
@@ -105,8 +107,10 @@ function App({
             isAppBarVisible={isAppBarVisible}
           >
             {isNavBarVisible && <Navbar />}
-            <AppContent>
-              {errorPage ? getErrorComponent(errorPage) : children}
+            <AppContent ref={setViewportElement}>
+              <ContentViewportContext.Provider value={viewportElement ?? null}>
+                {errorPage ? getErrorComponent(errorPage) : children}
+              </ContentViewportContext.Provider>
             </AppContent>
             <UndoListing />
             <StatusListing />
diff --git a/frontend/src/metabase/core/context/ContentViewportContext.tsx b/frontend/src/metabase/core/context/ContentViewportContext.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..baae1ee233e7b70d7ede793e1c7f9e1005104935
--- /dev/null
+++ b/frontend/src/metabase/core/context/ContentViewportContext.tsx
@@ -0,0 +1,5 @@
+import React from "react";
+
+export const ContentViewportContext = React.createContext<HTMLElement | null>(
+  null,
+);
diff --git a/frontend/src/metabase/dashboard/components/DashboardGrid.jsx b/frontend/src/metabase/dashboard/components/DashboardGrid.jsx
index 42e0f656485dd502c398080f4135c825599eca6d..7c2b24a172af1e2dd827c47e32d8f858085ba8ca 100644
--- a/frontend/src/metabase/dashboard/components/DashboardGrid.jsx
+++ b/frontend/src/metabase/dashboard/components/DashboardGrid.jsx
@@ -20,6 +20,7 @@ import {
   DEFAULT_CARD_SIZE,
   MIN_ROW_HEIGHT,
 } from "metabase/lib/dashboard_grid";
+import { ContentViewportContext } from "metabase/core/context/ContentViewportContext";
 
 import _ from "underscore";
 import cx from "classnames";
@@ -31,6 +32,8 @@ import RemoveFromDashboardModal from "./RemoveFromDashboardModal";
 import DashCard from "./DashCard";
 
 class DashboardGrid extends Component {
+  static contextType = ContentViewportContext;
+
   constructor(props, context) {
     super(props, context);
 
@@ -172,7 +175,11 @@ class DashboardGrid extends Component {
   getRowHeight() {
     const { width } = this.props;
 
-    const hasScroll = window.innerWidth > document.documentElement.offsetWidth;
+    const contentViewportElement = this.context;
+    const hasScroll =
+      contentViewportElement?.clientHeight <
+      contentViewportElement?.scrollHeight;
+
     const aspectHeight = width / GRID_WIDTH / GRID_ASPECT_RATIO;
     const actualHeight = Math.max(aspectHeight, MIN_ROW_HEIGHT);