diff --git a/packages/docs/src/data/nav.json b/packages/docs/src/data/nav.json index 2997894a17d..a8d8ec9574c 100644 --- a/packages/docs/src/data/nav.json +++ b/packages/docs/src/data/nav.json @@ -69,6 +69,7 @@ "elevation", "flex", "float", + "grid", "opacity", "overflow", "position", diff --git a/packages/docs/src/examples/display-grid/auto-fill-cards.vue b/packages/docs/src/examples/display-grid/auto-fill-cards.vue new file mode 100644 index 00000000000..a34de8ca44d --- /dev/null +++ b/packages/docs/src/examples/display-grid/auto-fill-cards.vue @@ -0,0 +1,41 @@ + + + diff --git a/packages/docs/src/examples/display-grid/auto-fill-fit.vue b/packages/docs/src/examples/display-grid/auto-fill-fit.vue new file mode 100644 index 00000000000..4ecbb9560bb --- /dev/null +++ b/packages/docs/src/examples/display-grid/auto-fill-fit.vue @@ -0,0 +1,33 @@ + diff --git a/packages/docs/src/examples/display-grid/auto-fit-rows.vue b/packages/docs/src/examples/display-grid/auto-fit-rows.vue new file mode 100644 index 00000000000..436114bd129 --- /dev/null +++ b/packages/docs/src/examples/display-grid/auto-fit-rows.vue @@ -0,0 +1,14 @@ + diff --git a/packages/docs/src/examples/display-grid/auto-sizing-columns.vue b/packages/docs/src/examples/display-grid/auto-sizing-columns.vue new file mode 100644 index 00000000000..2a5f012af5d --- /dev/null +++ b/packages/docs/src/examples/display-grid/auto-sizing-columns.vue @@ -0,0 +1,16 @@ + diff --git a/packages/docs/src/examples/display-grid/basic-grid.vue b/packages/docs/src/examples/display-grid/basic-grid.vue new file mode 100644 index 00000000000..30abac02d34 --- /dev/null +++ b/packages/docs/src/examples/display-grid/basic-grid.vue @@ -0,0 +1,11 @@ + diff --git a/packages/docs/src/examples/display-grid/column-spanning.vue b/packages/docs/src/examples/display-grid/column-spanning.vue new file mode 100644 index 00000000000..0de40285134 --- /dev/null +++ b/packages/docs/src/examples/display-grid/column-spanning.vue @@ -0,0 +1,19 @@ + diff --git a/packages/docs/src/examples/display-grid/complex-layout.vue b/packages/docs/src/examples/display-grid/complex-layout.vue new file mode 100644 index 00000000000..bcb4473ac87 --- /dev/null +++ b/packages/docs/src/examples/display-grid/complex-layout.vue @@ -0,0 +1,39 @@ + diff --git a/packages/docs/src/examples/display-grid/grid-auto-sizing.vue b/packages/docs/src/examples/display-grid/grid-auto-sizing.vue new file mode 100644 index 00000000000..e9fe81a80ee --- /dev/null +++ b/packages/docs/src/examples/display-grid/grid-auto-sizing.vue @@ -0,0 +1,16 @@ + diff --git a/packages/docs/src/examples/display-grid/grid-flow-column.vue b/packages/docs/src/examples/display-grid/grid-flow-column.vue new file mode 100644 index 00000000000..04af7291035 --- /dev/null +++ b/packages/docs/src/examples/display-grid/grid-flow-column.vue @@ -0,0 +1,11 @@ + diff --git a/packages/docs/src/examples/display-grid/grid-positioning.vue b/packages/docs/src/examples/display-grid/grid-positioning.vue new file mode 100644 index 00000000000..2810080e3d7 --- /dev/null +++ b/packages/docs/src/examples/display-grid/grid-positioning.vue @@ -0,0 +1,19 @@ + diff --git a/packages/docs/src/examples/display-grid/grid-spans.vue b/packages/docs/src/examples/display-grid/grid-spans.vue new file mode 100644 index 00000000000..20292e2a6c8 --- /dev/null +++ b/packages/docs/src/examples/display-grid/grid-spans.vue @@ -0,0 +1,26 @@ + diff --git a/packages/docs/src/examples/display-grid/responsive-grid.vue b/packages/docs/src/examples/display-grid/responsive-grid.vue new file mode 100644 index 00000000000..feb48c374f5 --- /dev/null +++ b/packages/docs/src/examples/display-grid/responsive-grid.vue @@ -0,0 +1,13 @@ + diff --git a/packages/docs/src/pages/en/styles/grid.md b/packages/docs/src/pages/en/styles/grid.md new file mode 100644 index 00000000000..8a08b583241 --- /dev/null +++ b/packages/docs/src/pages/en/styles/grid.md @@ -0,0 +1,278 @@ +--- +meta: + title: Grid + description: Grid helper classes allow you to create responsive layouts using CSS Grid with utility classes. + keywords: grid helper classes, grid classes, css grid +related: + - /styles/flex/ + - /styles/display/ + - /components/grids/ +features: + report: true +--- + +# Grid + +Control the layout of grid containers with template definitions, item placement, and responsive grid utilities powered by CSS Grid. + + + +## Grid Template Classes + +| Class | Properties | +| - | - | +| **d-grid** | display: grid; | +| **grid-cols-1** | grid-template-columns: repeat(1, minmax(0, 1fr)); | +| **grid-cols-2** | grid-template-columns: repeat(2, minmax(0, 1fr)); | +| **grid-cols-3** | grid-template-columns: repeat(3, minmax(0, 1fr)); | +| **grid-cols-4** | grid-template-columns: repeat(4, minmax(0, 1fr)); | +| **grid-cols-5** | grid-template-columns: repeat(5, minmax(0, 1fr)); | +| **grid-cols-6** | grid-template-columns: repeat(6, minmax(0, 1fr)); | +| **grid-cols-7** | grid-template-columns: repeat(7, minmax(0, 1fr)); | +| **grid-cols-8** | grid-template-columns: repeat(8, minmax(0, 1fr)); | +| **grid-cols-9** | grid-template-columns: repeat(9, minmax(0, 1fr)); | +| **grid-cols-10** | grid-template-columns: repeat(10, minmax(0, 1fr)); | +| **grid-cols-11** | grid-template-columns: repeat(11, minmax(0, 1fr)); | +| **grid-cols-12** | grid-template-columns: repeat(12, minmax(0, 1fr)); | +| **grid-cols-none** | grid-template-columns: none; | +| **grid-rows-1** | grid-template-rows: repeat(1, minmax(0, 1fr)); | +| **grid-rows-2** | grid-template-rows: repeat(2, minmax(0, 1fr)); | +| **grid-rows-3** | grid-template-rows: repeat(3, minmax(0, 1fr)); | +| **grid-rows-4** | grid-template-rows: repeat(4, minmax(0, 1fr)); | +| **grid-rows-5** | grid-template-rows: repeat(5, minmax(0, 1fr)); | +| **grid-rows-6** | grid-template-rows: repeat(6, minmax(0, 1fr)); | +| **grid-rows-7** | grid-template-rows: repeat(7, minmax(0, 1fr)); | +| **grid-rows-8** | grid-template-rows: repeat(8, minmax(0, 1fr)); | +| **grid-rows-9** | grid-template-rows: repeat(9, minmax(0, 1fr)); | +| **grid-rows-10** | grid-template-rows: repeat(10, minmax(0, 1fr)); | +| **grid-rows-11** | grid-template-rows: repeat(11, minmax(0, 1fr)); | +| **grid-rows-12** | grid-template-rows: repeat(12, minmax(0, 1fr)); | +| **grid-rows-none** | grid-template-rows: none; | + +## Auto-Fill and Auto-Fit Classes + +| Class | Properties | +| - | - | +| **grid-cols-auto-fill-100** | grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); | +| **grid-cols-auto-fill-150** | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); | +| **grid-cols-auto-fill-200** | grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); | +| **grid-cols-auto-fill-250** | grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); | +| **grid-cols-auto-fill-300** | grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); | +| **grid-cols-auto-fill-350** | grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); | +| **grid-cols-auto-fill-400** | grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); | +| **grid-cols-auto-fill-500** | grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); | +| **grid-cols-auto-fit-100** | grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); | +| **grid-cols-auto-fit-150** | grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | +| **grid-cols-auto-fit-200** | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | +| **grid-cols-auto-fit-250** | grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | +| **grid-cols-auto-fit-300** | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | +| **grid-cols-auto-fit-350** | grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); | +| **grid-cols-auto-fit-400** | grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); | +| **grid-cols-auto-fit-500** | grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); | +| **grid-rows-auto-fill-100** | grid-template-rows: repeat(auto-fill, minmax(100px, 1fr)); | +| **grid-rows-auto-fill-150** | grid-template-rows: repeat(auto-fill, minmax(150px, 1fr)); | +| **grid-rows-auto-fill-200** | grid-template-rows: repeat(auto-fill, minmax(200px, 1fr)); | +| **grid-rows-auto-fill-250** | grid-template-rows: repeat(auto-fill, minmax(250px, 1fr)); | +| **grid-rows-auto-fill-300** | grid-template-rows: repeat(auto-fill, minmax(300px, 1fr)); | +| **grid-rows-auto-fill-350** | grid-template-rows: repeat(auto-fill, minmax(350px, 1fr)); | +| **grid-rows-auto-fill-400** | grid-template-rows: repeat(auto-fill, minmax(400px, 1fr)); | +| **grid-rows-auto-fill-500** | grid-template-rows: repeat(auto-fill, minmax(500px, 1fr)); | +| **grid-rows-auto-fit-100** | grid-template-rows: repeat(auto-fit, minmax(100px, 1fr)); | +| **grid-rows-auto-fit-150** | grid-template-rows: repeat(auto-fit, minmax(150px, 1fr)); | +| **grid-rows-auto-fit-200** | grid-template-rows: repeat(auto-fit, minmax(200px, 1fr)); | +| **grid-rows-auto-fit-250** | grid-template-rows: repeat(auto-fit, minmax(250px, 1fr)); | +| **grid-rows-auto-fit-300** | grid-template-rows: repeat(auto-fit, minmax(300px, 1fr)); | +| **grid-rows-auto-fit-350** | grid-template-rows: repeat(auto-fit, minmax(350px, 1fr)); | +| **grid-rows-auto-fit-400** | grid-template-rows: repeat(auto-fit, minmax(400px, 1fr)); | +| **grid-rows-auto-fit-500** | grid-template-rows: repeat(auto-fit, minmax(500px, 1fr)); | + +## Grid Item Placement Classes + +| Class | Properties | +| - | - | +| **col-auto** | grid-column: auto; | +| **col-span-1** | grid-column: span 1 / span 1; | +| **col-span-2** | grid-column: span 2 / span 2; | +| **col-span-3** | grid-column: span 3 / span 3; | +| **col-span-4** | grid-column: span 4 / span 4; | +| **col-span-5** | grid-column: span 5 / span 5; | +| **col-span-6** | grid-column: span 6 / span 6; | +| **col-span-7** | grid-column: span 7 / span 7; | +| **col-span-8** | grid-column: span 8 / span 8; | +| **col-span-9** | grid-column: span 9 / span 9; | +| **col-span-10** | grid-column: span 10 / span 10; | +| **col-span-11** | grid-column: span 11 / span 11; | +| **col-span-12** | grid-column: span 12 / span 12; | +| **col-span-full** | grid-column: 1 / -1; | +| **col-start-1** | grid-column-start: 1; | +| **col-start-2** | grid-column-start: 2; | +| **col-start-3** | grid-column-start: 3; | +| **col-start-4** | grid-column-start: 4; | +| **col-start-5** | grid-column-start: 5; | +| **col-start-6** | grid-column-start: 6; | +| **col-start-7** | grid-column-start: 7; | +| **col-start-8** | grid-column-start: 8; | +| **col-start-9** | grid-column-start: 9; | +| **col-start-10** | grid-column-start: 10; | +| **col-start-11** | grid-column-start: 11; | +| **col-start-12** | grid-column-start: 12; | +| **col-start-13** | grid-column-start: 13; | +| **col-end-1** | grid-column-end: 1; | +| **col-end-2** | grid-column-end: 2; | +| **col-end-3** | grid-column-end: 3; | +| **col-end-4** | grid-column-end: 4; | +| **col-end-5** | grid-column-end: 5; | +| **col-end-6** | grid-column-end: 6; | +| **col-end-7** | grid-column-end: 7; | +| **col-end-8** | grid-column-end: 8; | +| **col-end-9** | grid-column-end: 9; | +| **col-end-10** | grid-column-end: 10; | +| **col-end-11** | grid-column-end: 11; | +| **col-end-12** | grid-column-end: 12; | +| **col-end-13** | grid-column-end: 13; | +| **row-auto** | grid-row: auto; | +| **row-span-1** | grid-row: span 1 / span 1; | +| **row-span-2** | grid-row: span 2 / span 2; | +| **row-span-3** | grid-row: span 3 / span 3; | +| **row-span-4** | grid-row: span 4 / span 4; | +| **row-span-5** | grid-row: span 5 / span 5; | +| **row-span-6** | grid-row: span 6 / span 6; | +| **row-span-7** | grid-row: span 7 / span 7; | +| **row-span-8** | grid-row: span 8 / span 8; | +| **row-span-9** | grid-row: span 9 / span 9; | +| **row-span-10** | grid-row: span 10 / span 10; | +| **row-span-11** | grid-row: span 11 / span 11; | +| **row-span-12** | grid-row: span 12 / span 12; | +| **row-span-full** | grid-row: 1 / -1; | +| **row-start-1** | grid-row-start: 1; | +| **row-start-2** | grid-row-start: 2; | +| **row-start-3** | grid-row-start: 3; | +| **row-start-4** | grid-row-start: 4; | +| **row-start-5** | grid-row-start: 5; | +| **row-start-6** | grid-row-start: 6; | +| **row-start-7** | grid-row-start: 7; | +| **row-start-8** | grid-row-start: 8; | +| **row-start-9** | grid-row-start: 9; | +| **row-start-10** | grid-row-start: 10; | +| **row-start-11** | grid-row-start: 11; | +| **row-start-12** | grid-row-start: 12; | +| **row-start-13** | grid-row-start: 13; | +| **row-end-1** | grid-row-end: 1; | +| **row-end-2** | grid-row-end: 2; | +| **row-end-3** | grid-row-end: 3; | +| **row-end-4** | grid-row-end: 4; | +| **row-end-5** | grid-row-end: 5; | +| **row-end-6** | grid-row-end: 6; | +| **row-end-7** | grid-row-end: 7; | +| **row-end-8** | grid-row-end: 8; | +| **row-end-9** | grid-row-end: 9; | +| **row-end-10** | grid-row-end: 10; | +| **row-end-11** | grid-row-end: 11; | +| **row-end-12** | grid-row-end: 12; | +| **row-end-13** | grid-row-end: 13; | + +## Grid Flow and Auto Sizing Classes + +| Class | Properties | +| - | - | +| **grid-flow-row** | grid-auto-flow: row; | +| **grid-flow-col** | grid-auto-flow: column; | +| **grid-flow-dense** | grid-auto-flow: dense; | +| **grid-flow-row-dense** | grid-auto-flow: row dense; | +| **grid-flow-col-dense** | grid-auto-flow: column dense; | +| **auto-cols-auto** | grid-auto-columns: auto; | +| **auto-cols-min** | grid-auto-columns: min-content; | +| **auto-cols-max** | grid-auto-columns: max-content; | +| **auto-cols-fr** | grid-auto-columns: minmax(0, 1fr); | +| **auto-rows-auto** | grid-auto-rows: auto; | +| **auto-rows-min** | grid-auto-rows: min-content; | +| **auto-rows-max** | grid-auto-rows: max-content; | +| **auto-rows-fr** | grid-auto-rows: minmax(0, 1fr); | + + + +## Usage + +Using `display` utilities you can turn any element into a CSS Grid container transforming **direct children elements** into grid items. Using additional grid property utilities, you can customize their layout even further. + + + +## Responsive Grid + +You can also customize grid utilities, `grid-{breakpoint}-{value}`, to apply based upon various breakpoints. + + + +## Column Spanning + +The `col-span-{n}` and `row-span-{n}` utility classes make grid items span multiple columns or rows: + + + +## Grid Positioning + +The `col-{n}` and `row-{n}` utility classed position items at specific grid locations: + + + +## Complex Layouts + +Combine multiple grid utilities for complex layouts: + + + +## Auto-Fill and Auto-Fit + +Auto-fill and auto-fit create responsive grids that automatically adjust the number of columns based on available space. + +Auto-Fill `grid-cols-auto-fill-{size}` + +- **Maintains empty columns** when there aren't enough items to fill the row +- Creates as many columns as can fit based on the minimum size +- Empty columns remain in the layout (invisible but present) +- Items keep their minimum width even with extra space + +Auto-Fit `grid-cols-auto-fit-{size}` + +- **Stretches items** to fill all available space +- Collapses empty columns and expands filled ones +- Items grow to use the full container width +- No empty columns remain in the layout + + + +### Practical Usage + +Auto-fill works great for card layouts where you want consistent item sizes: + + + +## Grid Flow + +Control how auto-placed items flow in the grid: + + + +## Auto Sizing + +Control the size of rows implicitly created grid tracks using `grid-auto-rows-min`: + + + +Control the size of rows implicitly created grid tracks using `grid-auto-cols-min`: + + + +## Responsive Variants + +All grid classes support responsive variants. Use the format `{class}-{breakpoint}-{value}`. + +## Caveats + +::: info +Grid utilities use `!important` in their styling to ensure they override other CSS rules. This is similar to other utility classes in Vuetify. +::: + +::: warning +Auto-fill and auto-fit rows work best in containers with defined heights. Without a height constraint, rows may not behave as expected. +::: diff --git a/packages/vuetify/src/styles/settings/_utilities.scss b/packages/vuetify/src/styles/settings/_utilities.scss index d6d600a93a5..b4094721c4d 100644 --- a/packages/vuetify/src/styles/settings/_utilities.scss +++ b/packages/vuetify/src/styles/settings/_utilities.scss @@ -24,7 +24,7 @@ $utilities: () !default; print: true, property: display, class: d, - values: none inline inline-block block table table-row table-cell flex inline-flex + values: none inline inline-block block table table-row table-cell flex inline-flex grid ), "float": ( responsive: true, @@ -176,6 +176,96 @@ $utilities: () !default; ), ), + // Grid utilities + "grid-template-columns": ( + responsive: true, + property: grid-template-columns, + class: grid-cols, + values: map.merge( + generate-grid-template(12), + generate-auto-variants() + ), + ), + "grid-template-rows": ( + responsive: true, + property: grid-template-rows, + class: grid-rows, + values: map.merge( + generate-grid-template(12), + generate-auto-variants() + ), + ), + "grid-column": ( + responsive: true, + property: grid-column, + class: col, + values: generate-grid-spans(12), + ), + "grid-row": ( + responsive: true, + property: grid-row, + class: row, + values: generate-grid-spans(12), + ), + "grid-column-start": ( + responsive: true, + property: grid-column-start, + class: col-start, + values: generate-grid-start-end(13), + ), + "grid-column-end": ( + responsive: true, + property: grid-column-end, + class: col-end, + values: generate-grid-start-end(13), + ), + "grid-row-start": ( + responsive: true, + property: grid-row-start, + class: row-start, + values: generate-grid-start-end(13), + ), + "grid-row-end": ( + responsive: true, + property: grid-row-end, + class: row-end, + values: generate-grid-start-end(13), + ), + "grid-auto-flow": ( + responsive: true, + property: grid-auto-flow, + class: grid-flow, + values: ( + row: row, + col: column, + dense: dense, + row-dense: row dense, + col-dense: column dense, + ), + ), + "grid-auto-columns": ( + responsive: true, + property: grid-auto-columns, + class: auto-cols, + values: ( + auto: auto, + min: min-content, + max: max-content, + fr: minmax(0, 1fr), + ), + ), + "grid-auto-rows": ( + responsive: true, + property: grid-auto-rows, + class: auto-rows, + values: ( + auto: auto, + min: min-content, + max: max-content, + fr: minmax(0, 1fr), + ), + ), + // gap utilities "gap": ( responsive: true, diff --git a/packages/vuetify/src/styles/tools/_functions.sass b/packages/vuetify/src/styles/tools/_functions.sass index 17e47df0010..efa5f43025d 100644 --- a/packages/vuetify/src/styles/tools/_functions.sass +++ b/packages/vuetify/src/styles/tools/_functions.sass @@ -80,3 +80,34 @@ @function roundEven($val) @return 2 * math.round($val * .5) + +// Grid utility generation functions +@function generate-grid-template($max: 12) + $values: () + @for $i from 1 through $max + $values: map.merge($values, (#{$i}: repeat(#{$i}, minmax(0, 1fr)))) + @return map.merge($values, (none: none)) + +@function generate-auto-variants($sizes: (100, 150, 200, 250, 300, 350, 400, 500)) + $values: () + @each $size in $sizes + $values: map.merge($values, (auto-fill-#{$size}: repeat(auto-fill, minmax(#{$size}px, 1fr)), auto-fit-#{$size}: repeat(auto-fit, minmax(#{$size}px, 1fr)))) + @return $values + +@function generate-grid-positions($max: 12) + $values: (auto: auto) + @for $i from 1 through $max + $values: map.merge($values, (#{$i}: #{$i})) + @return $values + +@function generate-grid-spans($max: 12) + $values: (auto: auto) + @for $i from 1 through $max + $values: map.merge($values, (#{$i}: #{$i}, span-#{$i}: span #{$i} / span #{$i})) + @return map.merge($values, (span-full: 1 / -1)) + +@function generate-grid-start-end($max: 13) + $values: (auto: auto) + @for $i from 1 through $max + $values: map.merge($values, (#{$i}: #{$i})) + @return $values