Shipping the 20-Component Beta: The Mechanics of Dynamic Greedy Row Masonry
How Exhuma achieved O(N log K) greedy shortest-column masonry balancing with zero layout thrashing, single-frame coalesced rAF, and universal parity across 13 ecosystems.
- 8 min read
- October 2026
- Authored by Fleect
- Layout Engines
- Masonry
- Compositor
- Milestone
The Masonry Conundrum: CSS Columns vs. DOM Thrashing
For years, frontend developers faced an unpleasant compromise when building masonry grids: either rely on native CSS column-count or pull in heavy JavaScript libraries like Macy.js, Masonry.js, or Isotope. Native CSS column-count is fast and zero-runtime, but it orders items vertically down Column 1, then down Column 2. In any chronological feed, blog list, or dynamic catalog, this breaks natural reading order—the second item appears far down the screen instead of adjacent to the first. Conversely, traditional JavaScript masonry libraries mutate inline DOM style.top and style.left synchronously during image load events and window resize loops. This triggers continuous forced synchronous reflows—layout thrashing—that spike Interaction to Next Paint (INP) and devastate mobile performance.
Greedy Shortest-Column Placement in O(N log K)
Exhuma RowMasonry eliminates this tradeoff entirely through the Exhuma Kinetic Methodology (EKM). Instead of inline CSS positioning, it maintains a running vector of column heights H = [h₀, h₁, ..., h_{K-1}]. For each child item with measured height H_i, the layout engine selects the column with the minimum cumulative height and assigns absolute translation offsets.
// Pure headless greedy masonry placement in O(N log K)
export function computeMasonryLayout(
itemHeights: number[],
containerWidth: number,
columns: number,
gap: number
): { items: MasonryItem[]; totalHeight: number } {
const colWidth = (containerWidth - gap * (columns - 1)) / columns;
const colHeights = new Array(columns).fill(0);
const items = itemHeights.map((h, index) => {
// Find shortest column
let minCol = 0;
for (let c = 1; c < columns; c++) {
if (colHeights[c] < colHeights[minCol]) minCol = c;
}
const x = minCol * (colWidth + gap);
const y = colHeights[minCol];
colHeights[minCol] += h + gap;
return { index, x, y, width: colWidth };
});
const totalHeight = Math.max(...colHeights, 0);
return { items, totalHeight };
}Single-Frame Coalesced rAF & Dynamic Media Capture
Real-world masonry grids must handle asynchronously loading images, videos, and dynamic user cards. If 20 images resolve within 100 milliseconds, naïve listeners schedule 20 separate layout recalculations. RowMasonry solves this with two cooperating mechanisms: 1. Event Capture for Media: An event listener attached to the container with capture: true intercepts the load event of every descending <img> or <video> element as soon as it arrives, without requiring per-child wrapper props. 2. Single-Frame Coalescing: All resize events, observer callbacks, and image load triggers channel into a single requestAnimationFrame handle (rafIdRef). If multiple triggers fire within the same browser frame, intermediate calls coalesce into a single execution pass. All item positions are applied directly via hardware-accelerated transform: translate3d(x, y, 0), leaving normal-flow DOM geometry intact.
The 20-Component Milestone Across 13 Ecosystems
The addition of RowMasonry marks the official completion of Exhuma’s 20-Component Beta milestone. From tactile cards (StackingCards, TiltCard, SpotlightCard, BorderBeam, CardSwipeStack, ComparisonSlider, ExpandableCard, HorizontalScroller) to navigation rails (MorphingTabs, FloatingDock) and kinetic layout engines (CssMasonry, RowMasonry, AutoGrid, InfiniteMarquee, BentoGrid, DiamondGrid), every primitive is available across all 13 supported frontend ecosystems. Whether you consume components via pnpm add @exhuma/core or generate zero-dependency copy-paste source code for React, Next.js, Vue 3, Svelte 5, Angular 19, or Flutter using npx exhuma add, you get 100% owned source code engineered for peak tactile performance.
# Add RowMasonry to your project with your preferred framework flavor
npx exhuma add row-masonry --flavor=react
# Or install the unified flagship engine
pnpm add @exhuma/core @exhuma/layouts