How to vertically center align the bottom of a horizontal list of items of varying heights

Viewed 108

I'm trying to achieve the following layout without using absolute positioning

enter image description here

The reason is that I would like to use css grid or flexbox as much as possible and try to avoid taking thins out of the flow if at all possible. In this case the surrounding div has a padding which should be respected, if it comes to that, and instead it should increase it's height if necessary. Usually I use max-content with css grid to achieve this.

If it was only the text it would have been as easy as align-items: center; however, because of the images/badges, the text will not properly align in the center if I do this.

https://stackblitz.com/edit/react-ts-t4h6ff?file=style.css

.list {
  width              : 100%;
  background         : red;
  display            : flex;
  flex-direction     : row;
  align-items        : center;
  }
.list-item {
  background         : yellow;
  display            : grid;
  grid-template-rows : max-content max-content;
  padding            : 1rem;
  }
<div class="list">
  <div class="list-item">list item 1</div>
  <div class="list-item">
    <div>image</div>
    <div>list item 2</div>
  </div>
  <div class="list-item">
    <div>image</div>
    <div>list item 3</div>
  </div>
</div>

Basically https://stackblitz.com/edit/react-ts-4xy14d?file=style.css is what I want to achieve, but without position absolute or transform translate.

Ended up with: https://stackblitz.com/edit/react-ts-78pckz?file=style.css

html,
body,
#root,
.wrapper {
  height: 100%;
  width: 100%;
}

.wrapper {
  display: grid;
  grid-template-rows: minmax(5rem, 50%) auto;
  background: purple;
}

.list {
  width: 100%;
  background: red;
  display: flex;
  flex-direction: row;
  height: 100%;
}
.list-item {
  background: yellow;
  display: grid;
  grid-template-rows: 1fr max-content 1fr;
  padding: 1rem;
  box-sizing: border-box;
  height: 100%;
  overflow: hidden;
}

.image-wrapper {
  position: relative;
}

.image {
  max-width: 100%;
  max-height: 100%;
  position: absolute;
  bottom: 0;
  right: 0;
}

.text {
  align-self: center;
  white-space: nowrap;
}
<div class="wrapper">
  <div class="list">
    <div class="list-item">
      <div> </div>
      <div class="text">list item 1</div>
      <div> </div>
    </div>
    <div class="list-item">
      <div class="image-wrapper">
        <img class="image" src="https://via.placeholder.com/100" />
      </div>
      <div class="text">list item 2</div>
      <div> </div>
    </div>
    <div class="list-item">
      <div class="image-wrapper">
        <img class="image" src="https://via.placeholder.com/150" />
      </div>
      <div class="text">list item 3</div>
      <div> </div>
    </div>
  </div>
  <div>... :-)</div>
</div>

1 Answers

I don't think it's the most elegant solution, but here's how I would solve the problem (assuming your diagram is saying that the size of the images are going to be consistent).

Edit: Didn't quite get there with my answers, but it did help Dac0d3r come up with this final solution. Source from him is in the comments.

  
  html,
  body,
  #root,
  .wrapper {
    height             : 100%;
    width              : 100%;
  }
  .wrapper {
    display            : grid;
    grid-template-rows : minmax(5rem, 50%) auto;
    background         : purple;
   }
  .list {
    width              : 100%;
    background         : red;
    display            : flex;
    flex-direction     : row;
    height             : 100%;
  }
  .list-item {
    background         : yellow;
    display            : grid;
    grid-template-rows : 50% 50%;
    padding            : 1rem;
    box-sizing         : border-box;
    height             : 100%;
  }

  .image {
     max-width         : 100%;
     max-height        : 100%;
     align-self        : end;
  }
  <div class="wrapper">
    <div class="list">
      <div class="list-item">
        <div></div>
        <div class="text">list item 1</div>
      </div>
      <div class="list-item">
        <img class="image" src="https://via.placeholder.com/100" />
        <div class="text">list item 2</div>
      </div>
      <div class="list-item">
        <img class="image" src="https://via.placeholder.com/150" />
        <div class="text">list item 3</div>
      </div>
    </div>
  </div>

Related