How can I create perfect squares for specific CSS grid items?

Viewed 138

I am trying to build a grid layout, where just the top-left, top-right, middle-left, and middle-right container make up a perfect square, while everything else should take up the space left. I saw solutions using a "padding-trick" and pseudo-elements to solve this, but only if all elements had to keep a specific aspect ratio.

.grid-container {
  display: grid;
  height: 100vh;
  width: 100%;

  grid-template-columns: 0.5fr 0.5fr 1.5fr;
  grid-template-rows: 7rem 0.5fr 0.5fr 2fr;
  gap: 1rem;
}

.grid-container > * {
  background-color: #454545;
}

.grid-header {
  grid-area: 1 / 1 / 2 / 4;
}

.top-left {
  grid-area: 2 / 1 / 3 / 2;
}

.top-right {
  grid-area: 2 / 2 / 3 / 3;
}

.middle-left {
  grid-area: 3 / 1 / 4 / 2;
}

.middle-right {
  grid-area: 3 / 2 / 4 / 3;
}

.bottom-left {
  grid-area: 4 / 1 / 5 / 3;
}

.bottom-right {
  grid-area: 2 / 3 / 5 / 4;
}
<div class="grid-container">
  <div class="grid-header"></div>
  <div class="top-left"></div>
  <div class="top-right"></div>
  <div class="middle-left"></div>
  <div class="middle-right"></div>
  <div class="bottom-left"></div>
  <div class="bottom-right"></div>
</div>

How could I achieve this while still being able to make it responsive?

1 Answers

If you make the row auto height you can use the padding trick

.grid-container {
  display: grid;
  height: 100vh;
  width: 100%;

  grid-template-columns: 0.5fr 0.5fr 1.5fr;
  grid-template-rows: 7rem auto auto 2fr;
  gap: 1rem;
}

.grid-container > * {
  background-color: #454545;
}

.grid-header {
  grid-column:1/-1;
}

.top-left::before,
.middle-left::before{
  content:"";
  display:inline-block;
  padding-top:100%;
}


.bottom-left {
  grid-area: 4 / 1 / 5 / 3;
}

.bottom-right {
  grid-area: 2 / 3 / 5 / 4;
}

body {
  margin:0;
}
<div class="grid-container">
  <div class="grid-header"></div>
  <div class="top-left"></div>
  <div class="top-right"></div>
  <div class="middle-left"></div>
  <div class="middle-right"></div>
  <div class="bottom-left"></div>
  <div class="bottom-right"></div>
</div>

Like below to make sure there is no overflow:

.grid-container {
  display: grid;
  height: 100vh;
  width: 100%;
  --d: calc((100vmin - 10rem)/2); /* take the smallest screen size and remove the gaps and header height */
  grid-template-columns: var(--d) var(--d) 1fr;
  grid-template-rows: 7rem var(--d) var(--d) 1fr;
  gap: 1rem;
}

.grid-container > * {
  background-color: #454545;
}

.grid-header {
  grid-column:1/-1;
}


.bottom-left {
  grid-area: 4 / 1 / 5 / 3;
}

.bottom-right {
  grid-area: 2 / 3 / 5 / 4;
}

body {
  margin:0;
}
<div class="grid-container">
  <div class="grid-header"></div>
  <div class="top-left"></div>
  <div class="top-right"></div>
  <div class="middle-left"></div>
  <div class="middle-right"></div>
  <div class="bottom-left"></div>
  <div class="bottom-right"></div>
</div>

Related