1

I haven't quite got my head around grid-template-areas, I suspect. Or maybe I do, but it is the behaviour of direct Grid descendant nodes that do not have a grid-area assigned.

Here is visually what I am trying to achieve:

visual example of desired outcome

Codepen is here: https://codepen.io/davewallace/pen/abYxWxE

Similar code example:

html, body , .container {
  height: 100%;
  margin: 0;
}

.container {
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: 1fr max-content;
  gap: 40px 40px;
  grid-template-areas:
    "header header"
    ". graphic";
}
.header { grid-area: header; }
.graphic { grid-area: graphic; }

/* For presentation only, no need to copy the code below */
.container * {
  border: 1px solid red;
  position: relative;
}
<div class="container">
  <div class="header">Full-width title</div>
  <div class="graphic">Graphic</div>
  <h4>Random element here</h4>
  <p>Random element here</p>
  <p>Random element here</p>
</div>

I seem to be able to only achieve two things currently:

  1. Everything is in the right place, but all "generic content items" overlap on top of each other, where instead I want them stacked.
  2. The title is in the right place, the image is sort of in the right place, but columns and/or rows are added automatically and do things like wrap under the image

The MDN docs for grid-template-area haven't really cleared the mix of behaviours up for me. I also tried using https://grid.layoutit.com/ to visualise the layout, and that seemed to get me off to a good start, but the default behaviour of the generic nodes has me confused.

connexo
  • 53,704
  • 14
  • 91
  • 128
danjah
  • 2,939
  • 2
  • 30
  • 47

2 Answers2

2

You can approximate it like below:

body {
  margin: 0;
}

.container {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr max-content;
  grid-auto-flow: dense;
  gap: 0 40px; /* set only column gap */
}

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

.graphic {
  grid-column: 2;
  grid-row: 2/ span 100; /* this will do the trick */
}

.container *:not(.graphic,:last-child) {
  margin-bottom: 40px; /* replace the row gap */
}


/* For presentation only, no need to copy the code below */

.container * {
  border: 1px solid red;
  position: relative;
  margin: 0;
}
<div class="container">
  <div class="header">Full-width title</div>
  <div class="graphic">Some Graphic here</div>
  <h4>Random element here</h4>
  <p>Random element here</p>
  <p>Random element here</p>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Nice trick..! I actually thought of that, but I missed setting `row-gap` as 0 and chrome went crazy by rendering a huge-ass grid container. – samuellawrentz Aug 25 '22 at 17:44
  • Aha, this is nice. Thank you. It didn't work in my live case, because the order of the elements `.graphic` and generic elements is also not known, it's as a result of a WYSIWYG action, so the user can drop in an image or text in any order. This is why I leaned on `grid-area`, I'd thought that by defining areas then the elements assigned to those areas would always reliably turn up in them. If you can think of a way that accommodates unknown order of generic nodes and the graphic, please do share your thoughts, I'd appreciate it! Otherwise, I can make do with what you've provided so far. – danjah Aug 26 '22 at 01:52
  • 1
    @danjah I made an update that should give the same result even if the order is random – Temani Afif Aug 26 '22 at 10:04
  • Ahh yes, that's just awesome, thank you @TemaniAfif – danjah Aug 28 '22 at 22:21
-1

I was trying to solve your CSS problem but it looks like there is no straightforward solution to it. According to the CSS spec, You cannot span a grid item to occupy all the rows/columns in an implicit grid.

Refer to this answer for more info - span grid item to all rows/columns

But I've come to a solution that could fix your grid by introducing a parent container for the random elements. In that way, you will only need two rows and two columns.

.container {
  display: grid;
  grid-template-columns: 1fr max-content;
  gap: 40px 40px;
  grid-template-areas: "header header" ". graphic";
}

.header {
  grid-area: header;
}

.graphic {
  grid-area: graphic;
}


/* Just to highlight */

.container * {
  border: 1px solid;
}
<div class="container">
  <div class="header">Full-width title</div>
  <div class="graphic">Graphic</div>
  <div class="random">
    <h4>Random element here1</h4>
    <p>Random element here2</p>
    <p>Random element here3</p>
    <p>Random element here4</p>
    <p>Random element here4</p>
    <p>Random element here4</p>
  </div>
</div>
samuellawrentz
  • 1,662
  • 11
  • 23