Skip to content

[css-grid] Better cell placement controls. #12658

@Westbrook

Description

@Westbrook

An author is able to apply any (I think 😉) of the following (and more) values to grid-template-columns/rows:

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    grid-template-columns: repeat(auto-fit, minmax(100px, 200px));
    grid-template-rows: repeat(auto-fill, minmax(100px, auto));
    grid-template-rows: repeat(auto-fill, minmax(100px, auto));
    /* ... etc ... */
}

And, in doing so, the author is ceding to the page the management of how many rows or columns will display at any one time. Which inversely means that at any one time the author is currently unable to know for sure how many columns or rows are being displayed to the visitor of their site. If said author wants to put something in the 5th cell (starting from the top/left) of the grid, how could they know for sure at any one time that the content is in that location?

Currently, authors can do this with fixed amounts of columns or rows by doing something like:

.grid {
    display: grid;
    grid-template-columns: repeat(var(--column-count), 100px);
    grid-template-rows: repeat(var(--row-count), 100px); 
    --column-count: 3;
    --row-count: 3;
}

.cell-5 {
    --cell: 5;
    grid-column: calc(mod((var(--cell) - 1), var(--column-count)) + 1);
    grid-row: round(down, calc((var(--cell) - 1) / var(--column-count) + 1));
}

Does CSS support authors in being responsive while also being exact?

Sort of...

See the fascinating work of @Noleli in this area: https://codepen.io/noleli/pen/QwjBWqz It really is quite amazing what we're able to do with the diversity of primitives the CSSWG has brought to life, but the specifics of this feel like more work that is appropriate for an author to need to manage. To make this work, we have all of the following intervening levels of complexity:

  • a grid element
  • a containing element for it on which to apply container queries
  • some advanced algebra
  • and 5 custom properties

That's just too much, right?

After creating Noah, he agrees:

The thing that suggests to me that maybe the CSSWG should consider something is that I as an author had to re-solve the same math that the layout engine does under the hood. Sure, it’s possible, but an author has to figure out the math and then the browser has to do it twice.

Options

I see two useful paths towards supporting authors in delivering content in this way. One is maybe more direct, the grid-cell property, while another maybe opens a broader array of capabilities over time, the grid-columns() and grid-rows() functions.

grid-cell

A grid-cell CSS property could work much like grid-column or grid-row but traverse multiple rows or columns to resolve it's location. In that way a flexible version of our target layout could be achieved with something like:

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 200px));
    grid-template-rows: repeat(auto-fill, minmax(100px, auto));
}

.cell-5 {
    grid-cell: 5;
}

Grid cell counting could/should follow text direction counting allowing the author to build off of the large flow of their content when targeting a specific cell to place their content in.

grid-columns() and grid-rows() functions

In line with the recently added sibling-count() CSS function, surfacing the actual number of columns or rows for use in the larger CSS construction could not only support the specifics of the example above, but possibly unlock various others that grid-cell may otherwise preclude. The CSS to leverage these properties is closer to the manual implementation, without the actual manual application:

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 200px));
    grid-template-rows: repeat(auto-fill, minmax(100px, auto));
}

.cell-5 {
    --cell: 5;
    grid-column: calc(mod((var(--cell) - 1), column-count()) + 1);
    grid-row: round(down, calc((var(--cell) - 1) / column-count() + 1));
}

Point of use resolution here would likely be important so that it would be possible to leverage compound grids and their column/row counts without context bleed:

<div class="grid-ancestor">
    <div class="cell-5 grid-descendent">
         <div class="cell-5"></div>
    </div>
</div>
<style>
.grid-ancestor {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 200px));
    grid-template-rows: repeat(auto-fill, minmax(100px, auto));
}

.grid-descendent {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(50px, auto));
    grid-template-rows: repeat(auto-fill, minmax(100px, 150px));
}

.cell-5 {
    --cell: 5;
    grid-column: calc(mod((var(--cell) - 1), column-count()) + 1);
    grid-row: round(down, calc((var(--cell) - 1) / column-count() + 1));
}
</style>

In this case for .grid-descendent.cell-5 the values of column-count() and row-count() would need to resolve to those created by .grid-ancestor, while for .grid-descendent > .cell-5 the value would need to resolve to those created by .grid-descendent.

The same should likely hold true to their application to CSS Custom Properties:

<div class="grid-ancestor">
    <div class="grid-descendent">
         <div class="cell"></div>
    </div>
</div>
<style>
.grid-ancestor {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 200px));
    grid-template-rows: repeat(auto-fill, minmax(100px, auto));
    --ancestor-column-count: column-count();
    --ancestor-row-count: row-count();
}

.grid-descendent {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(50px, auto));
    grid-template-rows: repeat(auto-fill, minmax(100px, 150px));
    --descendent-column-count: column-count();
    --descendent-row-count: row-count();
}

.cell {
    /* some magic incantation that relies on the discrete values of `--ancestor-column-count`, `--ancestor-row-count`, `--descendent-column-count`, and `--descendent-row-count`, while understanding the `--ancestor-column-count` vs `--descendent-column-count` and `--ancestor-row-count` vs `--descendent-row-count` will be specific to the realities of `.grid-ancestor` vs `.grid-descendent` and the respective grids that they deliver. */
}
</style>

Thanks for your conscideration! 🙇🏼‍♂️

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions