Note
This documentation describes the GridLayout Vue component for native UI views, for Xml templates see grid-layout.
GridLayout
A CSS Grid layout container with responsive breakpoint support and a simplified DSL for column/row templates.
Import
import { GridLayout } from '@neos/design-system'
Props
All props default to '' (empty, meaning the CSS property is not set).
Template DSL
The rows, columns, and rowsAuto props accept a space-separated string with the following shorthand values:
| DSL value | CSS equivalent |
|---|---|
* |
minmax(0, 1fr) — flexible fraction |
2* |
minmax(0, 2fr) — double fraction |
fit |
max-content — fit to content |
200 (bare number) |
200px — fixed pixels |
| Any valid CSS track | Passed through as-is |
Column/Row Template Props
| Prop | Notes |
|---|---|
columns |
Default column template |
columnsSmall |
Overrides columns on small screens |
columnsMedium |
Overrides columns on medium screens |
columnsLarge |
Overrides columns on large screens |
columnsExtralarge |
Overrides columns on extra-large screens |
columnsExtraextralarge |
Overrides columns on very large screens |
rows |
Default row template |
rowsSmall / rowsMedium / rowsLarge / rowsExtralarge |
Responsive row overrides |
rowsExtraextralarge |
Responsive row override (very large screens) |
rowsAuto |
Auto-generated row size (for implicit rows) |
rowsAutoSmall / rowsAutoMedium / rowsAutoLarge / rowsAutoExtralarge |
Responsive auto-row overrides |
rowsAutoExtraextralarge |
Responsive auto-row override (very large screens) |
Gap Props
| Prop | Type | Description |
|---|---|---|
gap |
Space |
Default gap between cells |
gapSmall / gapMedium / gapLarge / gapExtralarge / gapExtraextralarge |
Space |
Responsive gap overrides |
Slots
| Slot | Description |
|---|---|
default |
Grid cell children. Use style="--grid-column-span: n" on children to control the column span |
Responsive scope
| Prop | Type | Default | Description |
|---|---|---|---|
breakpointScope |
'window' \| 'container' |
'window' |
window (default): breakpoints react to the browser viewport, exactly as today. container: breakpoints react to the grid's own rendered width instead. |
thresholdSmall |
number |
undefined |
Custom pixel threshold for the small tier. Undefined keeps the standard value (640). |
thresholdMedium |
number |
undefined |
Custom pixel threshold for the medium tier. Undefined keeps the standard value (768). |
thresholdLarge |
number |
undefined |
Custom pixel threshold for the large tier. Undefined keeps the standard value (1024). |
thresholdExtralarge |
number |
undefined |
Custom pixel threshold for the extralarge tier. Undefined keeps the standard value (1280). |
thresholdExtraextralarge |
number |
undefined |
Custom pixel threshold for the extraextralarge tier. Undefined keeps the standard value (1536). |
Each threshold* prop is independent: set only the tiers you want to move, the others keep their standard value. Applies in container scope always, and in window scope whenever at least one threshold* prop is set.
Once every tier's value is resolved (custom or standard), they must be non-negative and strictly increasing. An invalid combination is ignored (with a console warning) and the standard thresholds are used instead for that render.
breakpointScope decides once, when the grid is created, whether and how its width gets measured; changing it afterwards on an already-rendered grid has no effect (the same behavior as the DataGrid card-mode-scope prop). To offer a live scope switch — for example in a demo — force Vue to recreate the component instead, such as by changing its :key.
A threshold* prop is different: if the grid already measures its width at creation (container scope, or window scope with at least one threshold* prop set), changing it afterwards still updates the thresholds live. It only has no effect if the grid started without measuring its width at all (window scope with no threshold* prop set at all) — force a recreation via :key in that case too.
Container-scope example
<GridLayout
breakpoint-scope="container"
:threshold-small="400"
:threshold-large="900"
columns-small="*"
columns-large="* * *"
gap="medium"
>
<Card v-for="item in items" :key="item.id">...</Card>
</GridLayout>
In a narrow panel or modal, this grid picks its column count from its own width — not the browser window's — so it never renders a desktop-width layout inside a space that can't fit it.
Window-scope example with custom thresholds
<GridLayout
:threshold-small="400"
:threshold-large="900"
columns-small="*"
columns-large="* * *"
gap="medium"
>
<Card v-for="item in items" :key="item.id">...</Card>
</GridLayout>
breakpointScope stays at its window default here, but the custom thresholds still apply: the grid keeps reacting to the browser viewport, just at the given thresholds instead of the standard ones.
Performance note
Both container scope and a custom threshold* prop in window scope replace the standard, free CSS media queries with a JavaScript-driven measurement (a ResizeObserver in container scope, a window resize listener otherwise). The cost per grid is small, but avoid enabling either on a very large number of simultaneously-rendered grids (for example, one per row of a long list) — prefer the default window scope without custom thresholds there, since it stays pure CSS.
Usage Examples
Two equal columns
<GridLayout columns="* *" gap="medium">
<StringFormField property-name="firstName" />
<StringFormField property-name="lastName" />
</GridLayout>
Three columns: fixed | flexible | fit-content
<GridLayout columns="200 * fit" gap="small">
<div>Sidebar</div>
<div>Main content</div>
<div>Aside</div>
</GridLayout>
Responsive: 1 column on small screens, 3 on large
<GridLayout columns-small="*" columns-large="* * *" gap="medium">
<Card v-for="item in items" :key="item.id">...</Card>
</GridLayout>
Child spanning multiple columns
<GridLayout columns="* * *" gap="small">
<StringFormField property-name="title" style="--grid-column-span: 3" />
<StringFormField property-name="firstName" />
<StringFormField property-name="lastName" />
<StringFormField property-name="email" />
</GridLayout>
Column and row spans
Set the column and row spans of a child with --grid-column-span and --grid-row-span in its style, and per breakpoint with --grid-column-span-small, --grid-row-span-medium and so on. A breakpoint without a value of its own takes the value of the smaller breakpoint. See Template directives.
<GridLayout columns="* * * *">
<div style="--grid-column-span: 4; --grid-column-span-medium: 2; --grid-row-span: 2">Wide and tall cell</div>
<div :style="{ '--grid-column-span': columnCount }">Computed span</div>
</GridLayout>