Home > Software engineering >  Preventing row above from pushing adjacent content down with grid
Preventing row above from pushing adjacent content down with grid

Time:10-15

I'm working with CSS Grid and I'm having a bit of trouble with a grid I created. The issue I'm having is that when the right column expands, it pushes content on the next row down below it on the left. For example you can see there's a large degree of spacing between orange (description) and blue (image) because of the green box (top-right). Ideally I'd like the right column to be able to push down, while keeping orange up against blue.

Image showing a problem with spacing in CSS grid

I've thought about different ways I could move this around to make this work better, and one of them is moving description so it's a child of image so it stays in the same row as it, but the problem is I need to be able to change the order of these items on different breakpoints, and on smaller screens I want orange to always be at the bottom, whereas moving the markup around results in it being near the top. Essentially the grid needs to flex in the way it does now, I just need to remove the whitespace in the screenshot above.

Here is the CSS:

$bp: 900px;

.page {
  &__grid {
    column-gap: 8px;
    display: grid;
    grid-template-columns: minmax(0, 70%) minmax(0, 30%);
    row-gap: 8px;
  }

  &__image {
    background-color: blue;
    height: 1080px;

    grid-column: span 1;
    grid-row: span 1;
    position: relative;

    @media screen and (min-width: $bp) {
      grid-row: span 3;
    }
  }

  &__description {
    background-color: orange;
    height: 300px;

    grid-column: 1;
    grid-row: span 1;
  }

  &__top-right {
    background-color: pink;
    height: 200px;

    grid-column: 1;
    order: -1;

    @media screen and (min-width: $bp) {
      grid-column: span 1;
      order: 0;
    }
  }

  &__right {
    background-color: green;
    height: 1200px;
    
    grid-column: 1;

    @media screen and (min-width: $bp) {
      grid-column: span 1;
    }
  }

  &__bottom-right {
    background-color: purple;
    height: 250px;

    grid-column: 2;
    grid-row: 1 / 6;
    position: relative;

    @media screen and (min-width: $bp) {
      grid-column: span 1;
      grid-row: span 4;
    }
  }
}

With the associated markup:

<div >

  <div >

    <div >
      Image
    </div>

    <div >
      Top right
    </div>

    <div >
      Right
    </div>

    <div >
      Bottom Right

    </div>

    <div >
      Description
    </div>

  </div>

</div>

I've also created a JSFiddle for this here: https://jsfiddle.net/coabnpg3/

Any help would be greatly appreciated! I have a feeling I'm over complicating this a fair amount.

CodePudding user response:

A possible solution would be to wrap each column. Maybe something like this:

.page__grid {
  display: flex;
  flex-direction: column;
}

.page__column {
  display: contents;
}

.page__blue {
  background-color: blue;
  height: 50px;
  order: 1;
}

.page__pink {
  background-color: pink;
  height: 50px;
  order: 2;
}

.page__orange {
  background-color: orange;
  height: 50px;
  order: 5;
}

.page__green {
  background-color: green;
  height: 50px;
  order: 3;
}

.page__purple {
  background-color: purple;
  height: 50px;
  order: 4;
}

@media screen and (min-width: 840px) {
  .page__grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
  }
  .page__column {
    display: flex;
    flex-direction: column;
  }
  .page__green {
    height: 80px;
  }
}
<div >
  <div >
    <div >
      <div >
        Blue
      </div>
      <div >
        Pink
      </div>
      <div >
        Orange
      </div>
    </div>
    <div >
      <div >
        Green
      </div>
      <div >
        Purple
      </div>
    </div>
  </div>
</div>

The trick is to add display: contents to the page__column element on mobile, so you can style you page as if these elements didn't exist.

On mobile, if you want them all under each other, you can use display flex and give the orange element the appropriate order number. You could also do it with css grid, either by adding grid areas or by setting the orange element's grid-row.

On desktop, you can add a display: flex to the page__column element. This allows elements on one column to grow without breaking the layout of the other column

  • Related