How can I fit content in visible page while using aspect-ratio?

I have a component on my page (named grid in the example).

I’d like this component to achieve the following constraints:
-1- maintain 1:1 aspect ratio
-2- be as big as possible
-3- stay within the bounds of the viewport (no scrollbars)
-4- ideally without JavaScript

I’ve been able to satisfy 1, 2, and 4, but not 3:

  • when the viewport is portrait-oriented (more height than width), the grid and its children will shrink as desired, to maintain the 1:1 aspect ratio.
  • when the viewport is landscape-oriented, the grid component expands beyond the bottom of the viewport, creating a scrollbar.

Here’s the HTML I’m looking at:

    <div id="wholePage" class="black">
      <div>top bar placeholder</div>
      <div id="grid">
        <div class="row darkGray">
          <div class="column red"></div>
          <div class="column yellow"></div>
        </div>
        <div class="row lightGray">
          <div class="column green"></div>
          <div class="column blue"></div>
        </div>
      </div>
    </div>

And here’s the associated CSS:

#wholePage {
  background-color: gray;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

#grid {
  width: auto;
  height: auto;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  aspect-ratio: 1;
}

.row {
  height: 50%;
  width: 100%;
  flex: 0 1 auto;
  display: flex;
  flex-direction: row;
}

.column {
  height: 100%;
  width: 100%;
  flex: 0 1 auto;
}

CSS

#wholePage {
  background-color: gray;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

#grid {
  flex: 1; /* Take up available space */
  aspect-ratio: 1 / 1; /* Maintain 1:1 aspect ratio */
  max-width: 100%; /* Prevent overflowing viewport */
  max-height: 100%; /* Prevent overflowing viewport */
}

.row {
  height: 50%;
  width: 100%;
  flex: 0 1 auto;
  display: flex;
  flex-direction: row;
}

.column {
  height: 100%;
  width: 100%;
  flex: 0 1 auto;
}

Explanation of changes:

  • flex: 1 on #grid: This allows the grid component to take up as much space as possible within its container.
  • aspect-ratio: 1 / 1 on #grid: This maintains the 1:1 aspect ratio, ensuring the grid component stays square.
  • max-width: 100% and max-height: 100% on #grid: These prevent the grid component from overflowing the viewport, ensuring it stays within the visible area.

With these modifications, the grid component should now:

  • Maintain a 1:1 aspect ratio.
  • Take up as much space as possible within the viewport.
  • Stay within the bounds of the viewport, preventing scrollbars.
  • Achieve these constraints without JavaScript.

This solution effectively addresses the issue you were facing, ensuring that your grid component behaves as desired in both portrait and landscape orientations.