Skip to content

[css-grid2] API for querying implicit grids #1465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MarkUK opened this issue May 25, 2017 · 7 comments
Closed

[css-grid2] API for querying implicit grids #1465

MarkUK opened this issue May 25, 2017 · 7 comments
Labels
css-grid-2 Subgrid; Current Work

Comments

@MarkUK
Copy link

MarkUK commented May 25, 2017

When using an implicit grid with automatically placed items, there seems to be no way to query the item to identify where it finally ended up, in row and column terms. Similarly it would be useful to be able to query the number of rows and columns in the grid, or get the bounding rect for a particular "cell".

Using getComputedStyle(), for example, does return useful values for grid-template-columns, but simply returns "auto" for grid-column-start and grid-row-start on an item in the grid.

A complementary API to get the element(s) at a particular row/column position would also be useful.

Use case: I have a UI layout that automatically places widgets in a grid to maximise the use of the available space. As a convenience I would like my users to be able to move vertically from field to field using the up/down cursor keys. To do this I need to find out the grid position of the current field, and then identify which field is in the cell directly above/below it.

There are, I'm sure, indirect ways to deal with this using getBoundingClientRect() or similar, but they are convoluted and fragile compared to being able to ask the grid to report information about itself.

@mrego mrego added the css-grid-2 Subgrid; Current Work label May 25, 2017
@fantasai
Copy link
Collaborator

fantasai commented May 8, 2018

It makes sense to me to have an API for this. I guess the way forward is for people to throw down proposals until one of them “sticks” (feels correct and intuitive enough to use as the basis of the new spec). :)

(Not sure if we'll be able to refine it in time for L2, whose goal is rapid stabilization of subgrid; but leaving it on the L2 tracker just in case.)

@MarkUK
Copy link
Author

MarkUK commented May 8, 2018

I guess it makes sense for me to make a proposal then, to get things going.

The first thing is probably to split my original request into three parts:

  1. Getting information about an item in the grid
  2. Getting information about the grid itself
  3. Getting information about the element(s) at a particular grid location

1: For the first case the requirement is to know the bounds of the item, in terms of grid lines. One possibility, therefore, would be to extend getComputedStyle() to also return the following properties:

  • gridRowStartNumber
  • gridRowEndNumber
  • gridColumnStartNumber
  • gridColumnEndNumber

Each of these properties should contain the computed line number, based on counting upwards from 1, even if the element itself is positioned using a negative index or with reference to a named area or lines.

For the sake of completeness, it may also be useful to return the following properties:

  • gridRowStartName
  • gridRowEndName
  • gridColumnStartName
  • gridColumnEndName

Each of these properties should contain the explicitly defined line name, or the implicitly generated name if one exists. Where a line name is defined more than once in a grid, the returned value should be followed by a single space and a numeric index, starting at 1. Where a line has more than one name (e.g. an explicit name, plus an implicit one from a grid area), a comma-separated list of name values should be returned.

Grid areas are not considered, other than through the fact that implicit line names are created when areas are used. If the target element is already positioned in a grid area through the "grid-area" CSS property this should already be exposed via the "gridArea" property returned from getComputedStyle() (see note below). If the target element happens to be positioned over a grid area (e.g. positioned using explicit line numbers which coincide with a defined grid area), this is only reflected through the line names that are returned.

NOTE: In my brief testing with Firefox and Chromium, it appears that getComputedStyle() returns less than useful values for elements positioned using "grid-area". For example "gridColumnStart" and "gridColumnEnd" both return the name of the grid area, without the implicit "-start" and "-end" suffixes of the line names, whilst "gridArea" returns distinctly different values between the browsers, neither
of which directly reflects the simple area name used in the original CSS. Perhaps this spec does need to be expanded to include definitions for the existing grid properties, to aid compatibility.

2: For the second situation, of returning information about the grid itself, once again getComputedStyle() could be extended, this time to include:

  • gridComputedColumns
  • gridComputedRows

Each property would contain a comma-separated list of pixel values, corresponding to the relative position of each line within the grid container. From this it would be easy for a competent developer to determine the number of rows and columns in the rendered grid, and the width and height of each of them.

3: Finally, for the third situation, of determining which children of the grid are positioned at a given location, I propose a method on the grid container, along the following lines:

NodeList   getGridItemsAtLocation(startColumn, startRow)

where startColumn and startRow are grid lines, defined by positive or negative number, or by reference to an explicit or implicitly named line.

This would return a static NodeList of all immediate grid children that have been positioned such that the cell whose top-left corner is at the intersection of the startColumn and startRow lines falls within the boundary of the child, ignoring any grid-gap values.

Examples:

getGridItemsAtLocation(1, 1)
// Returns all grid children that are positioned at the top-left of the grid

getGridItemsAtLocation(-1, 1)
// Returns all grid children that are positioned at the top-right of the grid

getGridItemsAtLocation(3, 4)
// Returns all grid children that are positioned such that they include the cell 
// defined by the overlap between the third column and fourth row 

getGridItemsAtLocation("fred", "wilma")
// Returns all grid children that are positioned such that they include the cell defined by 
// the overlap between the column which starts at the line named "fred" and the row which 
// starts at the line named "wilma"

getGridItemsAtLocation("sidebar-start", "sidebar-start")
// Returns all grid children that are positioned such that they include the cell at the 
// top-left of the "sidebar" named area, based on the implicit naming of lines 
// when grid-template-areas is used.

Note: I have not considered subgrids in any of this. My immediate thoughts are:

  • For the first item: children of subgrid elements should return values that correspond to the grid lines of the parent grid

  • For the second item: the line positions returned when querying a subgrid should include those lines of the parent grid that intersect with the subgrid element, but the values should be pixel positions relative to the top-left corner of the subgrid element, not the parent grid.

  • For the third item: the API should also be available on subgrid elements. When called on a grid that contains a subgrid, it should simply return the subgrid element in the NodeList if it overlaps with the specified position. It is down to the developer to further query the subgrid to identify which of its children overlap the position.

@tabatkins
Copy link
Member

Thanks for the suggestions! I ended up filing #2681 to track the first item (finding the actual location in the grid of a given item).

The other two suggestions seem simple to do on your own if #2681 is accepted; you just need to iterate the grid items and build up a map of their locations yourself. This won't handle anonymous grid items (created by raw text children of the grid container), but they're honestly an error case; we tried very hard to make anonymous grid/flex items fairly annoying to use, without actually hiding any data. ^_^

@MarkUK
Copy link
Author

MarkUK commented May 21, 2018

Thanks for opening issue #2681. With regard to the other items, I still think there's a requirement for the second one in particular. Note that the point of it was primarily to be able to find out the pixel positions of each row and column, which I don't think can be done simply by creating a map of the positioned items.

Consider that the row/column positions can be defined with complex CSS, including custom values, fr units, negative indexes, calc() and minmax(), and that the grid can be defined even without any content. The browser knows the calculated position of each row and column, but there's no way for script to query this.

The most obvious use cases can indeed be "solved" by ensuring the grid is fully populated by including empty divs, then using the gCS() (per issue #2681) to build up a map of the grid. But for more complex grids, with overlapping items and blank spaces - or simply if the developer doesn't want to add a load of empty divs - being able to find out the final position of each row and column line would make things a lot simpler.

@tabatkins
Copy link
Member

The sizes of explicit rows/columns will already be present in grid-template-rows and grid-template-columns from gCS(), since that also returns the used values, post-layout. It would just be implicit tracks that you'd have to figure out the bounds of.

And for implicit tracks, is there a use-case for knowing the sizes of tracks that don't have a corresponding item aligned to them? If you don't have an item edge touching a given line, that line basically doesn't exist, anyway.

@MarkUK
Copy link
Author

MarkUK commented May 22, 2018

You're right about grid-template-rows et al from gCS(). I'm not sure I was seeing those values in the browser when I first opened this request last year, but can't be certain.

As for implicit tracks, I was thinking along the lines of hit detection for placing items into a sparse grid. E.g. in my case of a UI layout, allowing users to move fields into empty spaces. But any such use case I can think of can be addressed by adding some extra empty divs and doing the hit detection on them (pending issue #2681 ).

Given that the use cases are not likely to be common, and there is a workaround of sorts, I'm closing this. Thanks for your feedback.

@MarkUK MarkUK closed this as completed May 22, 2018
@tabatkins
Copy link
Member

Ah, if your grid is fixed enough to let people drag things into empty spaces, then you don't need a special API at all. ^_^

But anyway, 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-grid-2 Subgrid; Current Work
Projects
None yet
Development

No branches or pull requests

4 participants