How to create a CSS Grid Layout box that spans 2 columns and 2 rows?
Asked Answered
D

3

32

I've created a grid layout following the newest CSS Grid spec, but am not completely familiar with it yet. I'm trying to create the following layout without having to define grid areas for each grid child.

codepen

body {
  max-width: 1024px;
  margin: 10px auto;
}

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas: "a a b" "a a c" "d e f";
}

.grid__thing {
  background-color: rebeccapurple;
}

.a {
  grid-area: a;
}

.b {
  grid-area: b;
}

.c {
  grid-area: c;
}

.d {
  grid-area: d;
}

.e {
  grid-area: e;
}

.f {
  grid-area: f;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="grid">
  <div class="grid__thing a">
    <img src="https://placehold.it/1360x880" alt="" />
  </div>
  <div class="grid__thing b">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing c">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing d">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing e">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
  <div class="grid__thing f">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
</div>

Ideally, I'd like to be able to set all the grid sizing properties in the grid parent and then ONLY define properties in grid item A to span across 2 columns and rows.

Currently specifying each grid area and attaching a unique class like so:

.grid {
    display: grid;
    grid-gap: 10px;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows:  1fr 1fr 1fr;
    grid-template-areas: "a a b"
                         "a a c"
                         "d e f";
.a {
    grid-area: a;
}
.b {
    grid-area: b;
}
.c {
    grid-area: c;
}
.d {
    grid-area: d;
}
.e {
    grid-area: e;
}
.f {
    grid-area: f;
}

Would like to do something like this so I don't have to create a unique CSS class for each grid item:

.grid {
    display: grid;
    grid-gap: 10px;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows:  1fr 1fr 1fr;
    grid-template-areas: "a a b"
                         "a a c"
                         "d e f";
}
.a {
    // The only unique selector, so this is the only thing that
    // should be given unique styling
}
Dibbell answered 7/6, 2017 at 0:28 Comment(0)
H
56

If you don't want to define grid areas for each grid item, then don't use the grid-template-areas property, which requires you to define names for each grid item.

Instead, just work with grid-template-columns and grid-template-rows on the container.

Then apply your 2x2 sizing to the first grid item using grid-column and grid-row.

grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  grid-gap: 10px;
}

grid_item:first-child {
  grid-column: 1 / 3; /* span from grid column line 1 to 3 (i.e., span 2 columns) */
  grid-row: 1 / 3;    /* same concept, but for rows */
}

/* non-essential decorative styles */
grid_item {
  background-color: aqua;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5em;
}
<grid-container>
  <grid_item>A</grid_item>
  <grid_item>B</grid_item>
  <grid_item>C</grid_item>
  <grid_item>D</grid_item>
  <grid_item>E</grid_item>
  <grid_item>F</grid_item>
</grid-container>

codepen demo

Hebraize answered 7/6, 2017 at 1:53 Comment(1)
Good answer, but I understand the question slightly different. May be I am wrong, however.Shirleenshirlene
M
24

instead of telling your element in what column / row it should start / end like in @Michael Benjamin's answer

grid-column: 1 / 3;

you could also tell your element how many rows / columns it should span

grid-column: span 2;
/*same rule as*/
grid-column-start: span 2;
grid-column-end: auto;

this way the element would be placed like it is placed in the document flow, but it would span multiple columns / rows.

you still can combine this rule with a start point ala

grid-column: 1 / span 2;
/*same rule as*/
grid-column-start: 1;
grid-column-end: span 2;

of course you can switch column with row to make the element span multiple rows

grid-row: span 2;
Martellato answered 17/11, 2022 at 14:44 Comment(1)
for the majority of people coming to this question, this is the correct (scalable) answerPrepense
S
3

Just do what you are planning; remove the useless classes.

body {
  max-width: 1024px;
  margin: 10px auto;
}

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas: "a a" "a a";
}

.grid__thing {
  background-color: rebeccapurple;
}

.a {
  grid-area: a;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="grid">
  <div class="grid__thing a">
    <img src="https://placehold.it/1360x880" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
</div>
Shirleenshirlene answered 7/6, 2017 at 16:34 Comment(3)
Then you're only using grid-template-areas to size and position element .a. The other elements are aligning based on the auto-placement algorithm, not grid-template-areas. If you decide to re-organize your layout, using grid-template-areas, all elements will be ignored, except .a.Hebraize
The answer above works, if you don't want to re-organize your layout, but it seems a bit inefficient, as letters b-f are useless, meaningless and arbitrary. You could replace those letters with anything, and nothing would change in the layout.Hebraize
@Michael_B Yes, you are right. I have fixed it. The truth is that I didn't really believed this was what the OP asked ...and just posted to be sureShirleenshirlene

© 2022 - 2024 — McMap. All rights reserved.