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 = OblyxGridGap._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 = OblyxGridGap._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 = OblyxGridGap._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 = OblyxGridGap._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 = OblyxGridGap._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 = OblyxGridGap._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 = OblyxGridRowGap._1, columnGap = OblyxGridColumnGap._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 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 = OblyxGridGap._3, align = OblyxGridAlign.CENTER, justify = OblyxGridJustify.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). |