Skip to content
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

[Feature] Support CSS Grid #63

Open
polarathene opened this issue Feb 11, 2020 · 5 comments
Open

[Feature] Support CSS Grid #63

polarathene opened this issue Feb 11, 2020 · 5 comments

Comments

@polarathene
Copy link

Opening this as a tracking issue.

I understand there is an intent for stretch to support CSS Grid in future, so for anyone interested in knowing when/if that happens, they can watch this issue for updates and/or show interest/support via 👍 reaction(to this issue, no +1 type comments thanks!).

While slightly biased due to React-Native using yoga for layout, there is strong interest in seeing CSS Grid support with little indication from yoga devs that the feature is on the horizon.

@nicoburns
Copy link

nicoburns commented Apr 19, 2020

So I spent a day yesterday looking into what it would take to implement CSS Grid in Stretch. And I thought I would write up my findings.

Useful Resources:

MVP Implementation Plan:

  • Extend the Style and Geometry sections of Stretch to include definitions for CSS Grid styles, while ensuring that the existing Flex implementation continues to work:

    • fr units
    • grid-template-columns/grid-template-rows/grid-template-areas
    • grid-auto-rows/grid-auto-columns/grid-auto-flow
    • grid-row-start/grid-row-end/grid-column-start/grid-column-end
    • row-gap/column-gap
  • Implement resolving the "explicit grid". This is the rows, columns and areas (cells) as defined by grid-template-columns/grid-template-rows/grid-template-areas (Sections 7.1-7.4 of the spec)

  • Implement grid placement. Matching Grid Items (child nodes of the grid) to Grid Areas. This may include generating extra rows and columns that form the "implicit grid" if any Grid Items are placed outside of the bounds of the "explicit grid". (note: the "implicit grid" is the whole grid, not just the extra bit) (Sections 7.5-8.5 of the spec)

  • Implement the Grid Sizing Algorithm to determine the size of each Grid Area. This mostly consists of the Track Sizing Algorithm, iterated a few times. A Grid Track is a row or column of the grid. (Section 11 of the spec).

  • Resolve Grid Item (node) sizes, by matching them to the Grid Areas.

Further tasks for full support:

  • Implement gutters, spacing and alignment (Section 10 of the spec)
  • Implement absolute positioning (Section 9 of the spec)
  • Support for aspect ratios
  • Support for CSS Grid Level 2 (subgrids)

Blocking questions / issues:

  • How should Grid interact with intrinsically sized leaf nodes. The spec seems to define child nodes as having both a min-size (e.g. text node that wraps at all opportunities) and max-size (e.g. a text node that doesn't wrap at all). Possibly these would need to be added to nodes as additional "measure functions"? Or possibly they could both be assumed to be equal to the one measure functions at first? Possibly min can be obtained by passing the MeasureFunc width: 0, height: 0, and max can be obtained by passing the MeasureFunc width: undefined, height: undefined? https://www.w3.org/TR/css-sizing-3/#intrinsic-contribution
  • The interaction between nested Grid and Flexbox nodes. The comment at https://github.com/vislyhq/stretch/blob/master/src/algo.rs#L373 suggests that the Flex implementation could be made more spec compliant by passing min-content/max-content constraints into to the top (presumably of the compute_internal function. I feel like this may be a prerequisite to getting Grid and Flex to play nicely with each other.

@emilsjolander Does this look about right to you? Do you have any comments, corrections, or suggestions?

@emilsjolander
Copy link
Contributor

@nicoburns this looks like a very solid plan. The only thing I can see is missing is testing :) One of the first steps should be extending the current test harnesses to support Grid and then also adding a significant number of test cases.

Really looking forward to seeing how this progresses! Please open up a PR early in the process just so we can help comment and see what is going on :)

@zacksabbath
Copy link

Very curious / excited to see where this goes!

@CooCooCaCha
Copy link

Awesome!

@polarathene
Copy link
Author

Would this type of Grid layout be useful for a test case? It uses fixed columns counts(repeat() + 1fr) until 1200px wide, then minmax() with repeat() to auto-fit as many columns of a min/max limit.

Rows are also a bit dynamic, and previously was a bit more complicated to keep the cells properly packed without unwanted spaces at certain viewport widths and rows. fit-content() resolved all that along with pre-processing the images to specific aspect ratios rather than relying on grid and CSS alone. The older CSS and images for that are available in git history if you'd want to use those for additional testing.

Then dense row packing is used since without that, empty spaces would not be filled. I think it's a good example of CSS grid.

Current CSS for grid is like this:

  background-color: #191723;

  display: grid;
  grid-gap: 5px;
  grid-auto-flow: row dense;
  grid-auto-rows: min-content;
  grid-template-columns: var(--column-count, 1fr);

  @media (min-width: 320px) {
    --column-count: 1fr 1fr;
  }
  @media (min-width: 640px) {
    --column-count: repeat(3, 1fr);
    /* Beneficial from this breakpoint forward */
    grid-auto-rows: fit-content(350px);
  }
  @media (min-width: 960px) {
    --column-count: repeat(4, 1fr);
  }
  /* Limit the width of cells from this size onwards */
  @media (min-width: 1200px) {
    --column-count: repeat(auto-fit, minmax(280px, 1fr));
  }

  /* These breakpoints have some unfilled areas, fill them */
  @media (min-width: 640px) and (max-width: 959.98px) {
    > div:nth-child(23) {
      grid-row: span 2;
    }
  }
  @media (min-width: 1705px) and (max-width: 2274.98px) {
    > div:nth-child(20) {
      grid-row: span 2;
      /* override internal inline style */
      img {
        object-position: left !important;
      }
    }
  }
  /* 2560px is next breakage */

  /* Related CSS on Grid item components: */
  @media (min-width: 320px) {
    ${props => props.type === "wide" && "grid-column: span 2;"}
    ${props => props.type === "tall" && "grid-row: span 2;"}
    ${props => props.type === "big" && "grid-column: span 2; grid-row: span 2;"}
  }

If not on a desktop device, here's some different viewport widths to show off the grid adapting:

2105x1692_50

1777x1692_50

1633x1692_50

1405x1692_50

Here we've reached fixed column breakpoints, and you can see how the vertical/tall cell in the middle has a more narrow aspect ratio to pack nicely into the grid, despite sharing the same CSS and image dimensions as the other tall images.
965s1692_50

640x1692_50

Just noticed that I need to push an update to the live version as it's presently using older CSS(some CSS variables to do calc() scaling at <720px on grid row/col values), which aren't necessary with the fit-content() rule I had switched to. At <640px, grid-auto-rows should be auto or min-content so that the single row/col grid items produce variable heights for some more interesting packing/layout variation like shown on the right here beside that tall two row cell:

540x1692_50

At <320px, every grid item is just 1 col/row spans:

293x1160_50

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants