VariableSizeList: Dynamic Row Heights
Handle items of different heights with VariableSizeList and the itemSize callback pattern.
VariableSizeList: Dynamic Row Heights is a free React Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
When Items Have Different Heights
Sometimes rows are not uniform: a chat list mixes short and long messages, or a feed has cards of varying content. FixedSizeList cannot handle this because it assumes one constant itemSize.
For these cases react-window offers a list type that lets each item declare its own size.
VariableSizeList Replaces FixedSizeList
VariableSizeList works like FixedSizeList but accepts a per-item size. You import it instead and provide a function that returns the size for any given index.
Everything else, the children render function and the critical style prop, stays the same, so the migration is small.
itemSize as a Function
With VariableSizeList, itemSize is a function that takes an index and returns that row height in pixels. react-window calls it to compute offsets and decide the visible window.
This lets you encode known heights, for example taller rows for items with images and shorter rows for plain text.
Pre-calculating vs Measuring
If you know each row height ahead of time, you can return it directly from the itemSize function. If heights depend on rendered content, you must measure rows after they paint.
Pre-calculated heights are simplest and fastest; measured heights are more flexible but require extra work to feed sizes back into the list.
resetAfterIndex After Measurement
VariableSizeList caches item offsets for performance. When a measured height changes, you must call the list resetAfterIndex method on its ref so it recomputes positions from that index onward.
Forgetting this leaves stale offsets and misaligned rows, so resetAfterIndex is the key to making dynamic measurement work.
The Height Catch-22
There is a chicken-and-egg problem: you need a height to render the row, but you only know the real height after it renders. The list must place a row before it can be measured.
Resolving this requires rendering with an estimate first, then correcting once the true height is known.
Estimate, Render, Measure, Update
The standard pattern is to render rows with an estimated height, measure their actual height after paint using a ref or ResizeObserver, store the measured value, and call resetAfterIndex to update positions.
This loop converges quickly so the list settles into correct offsets after the first measured pass.
getItemSize Must Be Stable
The itemSize function should be stable across renders, typically wrapped in useCallback, so the list does not constantly invalidate its cached offsets.
An unstable function defined inline can force unnecessary recalculation, hurting the performance virtualization is meant to provide.
The Performance Tradeoff
VariableSizeList does more work than FixedSizeList because it cannot assume a constant offset and must track per-item sizes. When heights are measured, the extra measurement adds cost too.
For lists where rows really do vary, this cost is worthwhile; for uniform rows, FixedSizeList remains the faster, simpler choice.
Falling Back to Fixed with Approximation
If exact dynamic measurement is too costly, you can sometimes approximate. Bucketing rows into a few fixed height classes, or using a reasonable average, can let you stay with FixedSizeList.
This trades pixel-perfect layout for simplicity and speed, an acceptable compromise when minor offset imperfections are tolerable.
Quick Check: VariableSizeList itemSize
Recall how VariableSizeList learns each row height.
Recap: VariableSizeList
VariableSizeList handles rows of differing heights by taking itemSize as a function of index. Heights can be pre-calculated or measured; measured heights need the estimate-render-measure-update loop with resetAfterIndex.
Keep the itemSize function stable with useCallback. It costs more than FixedSizeList, so for uniform rows, or when approximation suffices, prefer the fixed variant.
Frequently asked questions
Is the “VariableSizeList: Dynamic Row Heights” lesson free?
Yes — the full text of “VariableSizeList: Dynamic Row Heights” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “VariableSizeList: Dynamic Row Heights”?
Handle items of different heights with VariableSizeList and the itemSize callback pattern. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “VariableSizeList: Dynamic Row Heights” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Large List Rendering Problem
- FixedSizeList: Rendering Thousands of Items
- VariableSizeList: Dynamic Row Heights
- Combining Virtualization with Data Fetching