Search code examples
htmlcssreactjsgrid-layoutstyled-components

How to make grid rows take full height until they reach minimal size?


I have a div with a min-height of 90vh and a child div, that is set to be a grid, with max of 20 children and 5 columns of equal width. I want to set up a grid such that:

  • When it has =< 4 rows, they should take up the full min-height. So if there are 4 rows each of them should take 25% of the height, the same goes for 3 (33%), 2 (50%) and 1 (100%) rows.
  • When it has > 4 rows and the screen width is more than 600px (for example when column number goes down on smaller screens), each row takes 25% of its original height (22.5vh)
  • And on lesser screens, each row should take 12.5% of the original min-height (11.25vh)

I wonder if it is possible to set up such grid.

The code I have so far (I'm using styled-components):

const ColorBoxesWrap = styled.div`
  min-height: 90vh;
  width: 100%;
`;

const ColorBoxesGrid = styled.div`
  display: grid;
  grid-auto-rows: 11.25vh;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  @media (min-width: 1200px) {
    grid-template-columns: repeat(5, 1fr);
  }
  @media (min-width: 500px) {
    grid-auto-rows: 22.5vh;
  }
`;

Component:

...
<ColorBoxesWrap>
    <ColorBoxesGrid>{colorBoxes}</ColorBoxesGrid>
</ColorBoxesWrap>
...

This code does work for 15+ children, scaling and shrinking as needed. However, with =< 15, the rows still only take 25% of min-height.


Solution

  • The answer basically says it all, here is the code that I got in the end:

    const ColorBoxesWrap = styled.div`
      min-height: 90vh;
      width: 100%;
    `;
    
    const ColorBoxesGrid = styled.div`
      display: grid;
      grid-auto-rows: 11.25vh;
      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      @media (min-width: 500px) {
        grid-auto-rows: minmax(22.5vh, ${(props) => `${90 / Math.ceil(props.colorsCount / 2)}vh`});
      }
      @media (min-width: 750px) {
        grid-auto-rows: minmax(22.5vh, ${(props) => `${90 / Math.ceil(props.colorsCount / 3)}vh`});
      }
      @media (min-width: 1000px) {
        grid-auto-rows: minmax(22.5vh, ${(props) => `${90 / Math.ceil(props.colorsCount / 4)}vh`});
      }
      @media (min-width: 1200px) {
        grid-template-columns: repeat(5, 1fr);
        grid-auto-rows: minmax(22.5vh, ${(props) => `${90 / Math.ceil(props.colorsCount / 5)}vh`});
      }
    `;
    
    ...
    <ColorBoxesWrap>
        <ColorBoxesGrid colorsCount={colorsCount}>
            {colorBoxes}
        </ColorBoxesGrid>
    </ColorBoxesWrap>
    ...
    

    All media queries are set that way, as I can tell when it's going to wrap. Minmax is required for cells to be not smaller that 22.5vh. All the @media repetition might not be the best solution, but it works. Hope this helps somebody!