Grid
<oblyx-grid> is a two-dimensional CSS grid layout. Its children are ordinary grid items; <oblyx-grid-span> is an optional wrapper for a child that needs to cover more than one track. Unlike oblyx-stack and oblyx-layout, which are flexbox underneath, oblyx-grid really is display: grid.
Basic grid
<oblyx-grid columns="3" gap="3">
<div class="docs-demo-box">1</div>
<div class="docs-demo-box">2</div>
<div class="docs-demo-box">3</div>
<div class="docs-demo-box">4</div>
<div class="docs-demo-box">5</div>
</oblyx-grid>oblyxGrid(columns = 3, gap = OblyxSpacingStep._3) {
div(classes = "docs-demo-box") { +"1" }
div(classes = "docs-demo-box") { +"2" }
div(classes = "docs-demo-box") { +"3" }
div(classes = "docs-demo-box") { +"4" }
div(classes = "docs-demo-box") { +"5" }
}Spanning tracks
<oblyx-grid-span> covers multiple columns or rows. It IS the grid item its parent lays out (grid-column/grid-row are set on the tag itself, not an inner wrapper), so it composes as a plain child alongside items with no span at all. columns-full spans every column, for a row that should stretch edge to edge regardless of the grid's track count.
Grid span
<oblyx-grid columns="4" gap="3">
<oblyx-grid-span columns="2" class="docs-demo-box">Spans 2 columns</oblyx-grid-span>
<div class="docs-demo-box">3</div>
<div class="docs-demo-box">4</div>
<oblyx-grid-span columns-full class="docs-demo-box">columns-full: spans every column</oblyx-grid-span>
<div class="docs-demo-box">5</div>
</oblyx-grid>oblyxGrid(columns = 4, gap = OblyxSpacingStep._3) {
oblyxGridSpan(columns = 2) { classes = setOf("docs-demo-box"); +"Spans 2 columns" }
div(classes = "docs-demo-box") { +"3" }
div(classes = "docs-demo-box") { +"4" }
oblyxGridSpan(columnsFull = true) { classes = setOf("docs-demo-box"); +"columns-full: spans every column" }
div(classes = "docs-demo-box") { +"5" }
}Responsive columns
There's no breakpoint system here, matching upstream. Setting min-column-width(with columns left unset) switches the grid to an intrinsic auto-fill minmax() track template that the browser recomputes continuously as the container resizes, with no media query involved. Drag the bottom-right corner of the frame below to see the column count change in real time.
Responsive grid
Resize the dashed frame to change the column count.
<div class="docs-demo-resize">
<oblyx-grid min-column-width="140" gap="3">
<div class="docs-demo-box">1</div>
<div class="docs-demo-box">2</div>
<div class="docs-demo-box">3</div>
<div class="docs-demo-box">4</div>
<div class="docs-demo-box">5</div>
<div class="docs-demo-box">6</div>
</oblyx-grid>
</div>div {
classes = setOf("docs-demo-resize")
oblyxGrid(minColumnWidth = 140, gap = OblyxSpacingStep._3) {
div(classes = "docs-demo-box") { +"1" }
div(classes = "docs-demo-box") { +"2" }
div(classes = "docs-demo-box") { +"3" }
div(classes = "docs-demo-box") { +"4" }
div(classes = "docs-demo-box") { +"5" }
div(classes = "docs-demo-box") { +"6" }
}
}Fill vs. fit
repeat-mode only matters when there's room for more tracks than there are items.fill (the default) leaves the extra tracks empty, so items keep their natural track width;fit collapses the empty tracks instead, letting the present items stretch to fill the row. Both frames below are the same width with the same two items: only repeat-mode differs.
repeat-mode comparison
Resize either frame to see the difference persist at every width.
repeat-mode="fill" (default): empty tracks stay empty
repeat-mode="fit": empty tracks collapse, items stretch
<div>
<p class="docs-demo-label">repeat-mode="fill" (default): empty tracks stay empty</p>
<div class="docs-demo-resize" style="margin-bottom: 20px;">
<oblyx-grid min-column-width="100" gap="3">
<div class="docs-demo-box">1</div>
<div class="docs-demo-box">2</div>
</oblyx-grid>
</div>
<p class="docs-demo-label">repeat-mode="fit": empty tracks collapse, items stretch</p>
<div class="docs-demo-resize">
<oblyx-grid min-column-width="100" repeat-mode="fit" gap="3">
<div class="docs-demo-box">1</div>
<div class="docs-demo-box">2</div>
</oblyx-grid>
</div>
</div>div {
p(classes = "docs-demo-label") { +"repeat-mode=\"fill\" (default): empty tracks stay empty" }
div {
classes = setOf("docs-demo-resize")
oblyxGrid(minColumnWidth = 100, gap = OblyxSpacingStep._3) {
div(classes = "docs-demo-box") { +"1" }
div(classes = "docs-demo-box") { +"2" }
}
}
p(classes = "docs-demo-label") { +"repeat-mode=\"fit\": empty tracks collapse, items stretch" }
div {
classes = setOf("docs-demo-resize")
oblyxGrid(minColumnWidth = 100, repeatMode = OblyxGridRepeatMode.FIT, gap = OblyxSpacingStep._3) {
div(classes = "docs-demo-box") { +"1" }
div(classes = "docs-demo-box") { +"2" }
}
}
}Capping the column count
max-columns caps how many tracks the responsive mode will create, without abandoning the intrinsic resize behavior: the track minimum is clamped by the cap, but the track maximum stays 1fr, so the present columns still stretch to fill the row rather than leaving dead space on a narrow viewport.
Grid with max-columns
Resize the frame: it never exceeds 3 columns, but a lone column still fills the width.
<div class="docs-demo-resize">
<oblyx-grid min-column-width="100" max-columns="3" gap="3">
<div class="docs-demo-box">1</div>
<div class="docs-demo-box">2</div>
<div class="docs-demo-box">3</div>
<div class="docs-demo-box">4</div>
<div class="docs-demo-box">5</div>
<div class="docs-demo-box">6</div>
</oblyx-grid>
</div>div {
classes = setOf("docs-demo-resize")
oblyxGrid(minColumnWidth = 100, maxColumns = 3, gap = OblyxSpacingStep._3) {
div(classes = "docs-demo-box") { +"1" }
div(classes = "docs-demo-box") { +"2" }
div(classes = "docs-demo-box") { +"3" }
div(classes = "docs-demo-box") { +"4" }
div(classes = "docs-demo-box") { +"5" }
div(classes = "docs-demo-box") { +"6" }
}
}Gap
gap sets both axes at once, from the same spacing-token scale oblyx-stack and oblyx-layout use. row-gap and column-gap override one axis independently when they're also set.
Grid with independent row and column gap
<oblyx-grid columns="3" row-gap="1" column-gap="6">
<div class="docs-demo-box">1</div>
<div class="docs-demo-box">2</div>
<div class="docs-demo-box">3</div>
<div class="docs-demo-box">4</div>
<div class="docs-demo-box">5</div>
<div class="docs-demo-box">6</div>
</oblyx-grid>oblyxGrid(columns = 3, rowGap = OblyxSpacingStep._1, columnGap = OblyxSpacingStep._6) {
div(classes = "docs-demo-box") { +"1" }
div(classes = "docs-demo-box") { +"2" }
div(classes = "docs-demo-box") { +"3" }
div(classes = "docs-demo-box") { +"4" }
div(classes = "docs-demo-box") { +"5" }
div(classes = "docs-demo-box") { +"6" }
}Alignment
align (align-items) and justify (justify-items) position each item within its own track when the item is smaller than the track. Both take the same OblyxGridAlignment enum and default to stretch, matching upstream.
Grid item alignment
cell
<oblyx-grid columns="3" gap="3" align="center" justify="center" row-height="80">
<div class="docs-demo-box">Short</div>
<div class="docs-demo-box">A taller<br />cell</div>
<div class="docs-demo-box">Short</div>
</oblyx-grid>oblyxGrid(columns = 3, gap = OblyxSpacingStep._3, align = OblyxGridAlignment.CENTER, justify = OblyxGridAlignment.CENTER, rowHeight = 80) {
div(classes = "docs-demo-box") { +"Short" }
div(classes = "docs-demo-box") { +"A taller cell" }
div(classes = "docs-demo-box") { +"Short" }
}Reference
<oblyx-grid>
| Attribute | Type | Default | Description |
|---|---|---|---|
columns | number | undefined | – | Fixed track count -> repeat(columns, 1fr). Mutually exclusive with min-column-width's responsive mode; if both are set, this wins. Unset (and no min-column-width either) -> a single 1fr column, matching upstream's no-columns default. |
min-column-width | number | undefined | – | Minimum track width in pixels for the responsive auto-fill/ auto-fit mode (upstream's columns={{minWidth}}). Ignored when columns is set. |
max-columns | number | undefined | – | Caps the column count in responsive mode (upstream's columns={{minWidth, max}}). Meaningless without min-column-width. |
repeat-mode | fillfit | fill | auto-fill (default) vs auto-fit in responsive mode. |
gap | 00-511-523456810 | – | Gap between tracks on both axes, as a spacing-token step. Overridden per-axis by row-gap/column-gap when they're also set. |
row-gap | 00-511-523456810 | – | Row gap override. |
column-gap | 00-511-523456810 | – | Column gap override. |
row-height | number | undefined | – | Fixed row height in pixels (grid-auto-rows), for masonry-style layouts combined with oblyx-grid-span row spans. Unset -> auto. |
align | startcenterendstretch | stretch | Cross-axis-per-item alignment (align-items). |
justify | startcenterendstretch | stretch | Cross-axis-per-item alignment on the inline axis (justify-items). |
<oblyx-grid-span>
| Attribute | Type | Default | Description |
|---|---|---|---|
columns | number | undefined | – | Number of columns to span (grid-column: span columns). Mutually exclusive with columns-full, which wins if both are set. |
columns-full | boolean | false | Spans every column (grid-column: 1 / -1). An explicit boolean rather than overloading columns with a 'full' string value: attributes are the API, and a dedicated flag reads as intent rather than a magic string. |
rows | number | undefined | – | Number of rows to span (grid-row: span rows). |