Spans & stamps
Items that take two columns, and a pinned region the grid routes everything else around.
masonryColSpan widens an item across whole columns; the solver drops it into the group of columns with the lowest shared top edge. A masonryGridStamp element is positioned by you and treated as an obstacle. horizontalOrder switches from shortest-column packing to strict row order.
<!-- Widen an item with masonryColSpan, never with CSS width:
the grid writes item widths itself. A stamp is a region items
flow around; you position it, the grid routes around it. -->
<masonry-grid columnWidth="220" gutter="16">
<aside masonryGridStamp class="promo">Pinned</aside>
@for (card of cards(); track card.id) {
<article masonryGridItem [masonryColSpan]="card.span">
{{ card.title }}
</article>
}
</masonry-grid>