Corey Bruyere
Corey Bruyere

Reputation: 986

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

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
}

Upvotes: 40

Views: 109407

Answers (3)

Michael Benjamin
Michael Benjamin

Reputation: 372244

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

Upvotes: 61

vals
vals

Reputation: 64264

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>

Upvotes: 3

honk31
honk31

Reputation: 4387

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;

Upvotes: 30

Related Questions