diff --git a/docs/content/docs/2.components/table.md b/docs/content/docs/2.components/table.md
index 02f361002e..d31fca4615 100644
--- a/docs/content/docs/2.components/table.md
+++ b/docs/content/docs/2.components/table.md
@@ -686,6 +686,24 @@ class: '!p-0'
A height constraint is required on the table for virtualization to work properly (e.g., `class="h-[400px]"`).
::
+### Dynamic row heights :badge{label="Soon" class="align-text-top"}
+
+`estimateSize` is only the initial guess — the virtualizer measures every rendered row and updates its internal size map as you scroll. For rows with variable content (expandable rows, rich text, images), pass a `measureElement` callback to read the actual rendered height:
+
+```vue
+
+```
+
+When a row is expanded via `row.toggleExpanded()`, the expansion row's height is automatically added to the measurement — you don't need to walk siblings yourself.
+
### With tree data
You can use the `get-sub-rows` prop to display hierarchical (tree) data in the table.
diff --git a/src/runtime/components/Table.vue b/src/runtime/components/Table.vue
index 5e508c02aa..8931334771 100644
--- a/src/runtime/components/Table.vue
+++ b/src/runtime/components/Table.vue
@@ -99,6 +99,21 @@ export interface TableProps extends TableOption
meta?: TableMeta
/**
* Enable virtualization for large datasets.
+ *
+ * Pass a `measureElement` function to opt into dynamic row heights. The value returned by
+ * your `measureElement` is used as the height of the main row; when `row.getIsExpanded()`
+ * is `true`, the immediate next-sibling ``'s height is **added on top of** that value
+ * automatically, so your callback should measure the main row only. If your custom
+ * `measureElement` already includes the expanded region (e.g. by measuring a wrapper),
+ * return only the collapsed-row height to avoid double-counting.
+ *
+ * TanStack Virtual's `ResizeObserver` is attached to the main `
` only, and this
+ * component re-measures rows whenever the TanStack expanded state toggles. It does **not**
+ * observe size changes *inside* the expansion sibling — late-loading images, async content,
+ * or nested toggles that resize the expansion region after mount won't trigger an automatic
+ * re-measure. Call `virtualizer.measure()` (or `virtualizer.measureElement(row)`) yourself
+ * in those cases.
+ *
* Note: row pinning is not supported when virtualization is enabled.
* @see https://tanstack.com/virtual/latest/docs/api/virtualizer#options
* @defaultValue false
@@ -110,7 +125,8 @@ export interface TableProps extends TableOption
*/
overscan?: number
/**
- * Estimated size (in px) of each item, or a function that returns the size for a given index
+ * Estimated size (in px) of each item, or a function that returns the size for a given index.
+ * Used as the initial estimate before the virtualizer measures actual row heights.
* @defaultValue 65
*/
estimateSize?: number | ((index: number) => number)
@@ -224,7 +240,7 @@ export type TableSlots = {
-
+
-
+
|
|
@@ -625,7 +708,7 @@ defineExpose({