vislyhq / stretch

High performance flexbox implementation written in rust
https://vislyhq.github.io/stretch/
MIT License
1.99k stars 107 forks source link

[Feature] Support CSS Grid #63

Open polarathene opened 4 years ago

polarathene commented 4 years ago

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 :+1: 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 commented 4 years ago

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:

Further tasks for full support:

Blocking questions / issues:

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

emilsjolander commented 4 years ago

@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 commented 4 years ago

Very curious / excited to see where this goes!

CooCooCaCha commented 4 years ago

Awesome!

polarathene commented 4 years ago

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