9

I'm trying to vertically align variable height elements across containers, i.e. the 1st element in each container aligns vertically with each other, the 2nd element in each container aligns vertically with each other, etc., etc.

I'm using flexbox but not sure if this is even possible? Or is it possible using CSS Grid?

Desired outcome

enter image description here

See demo where I haven't managed to get it working yet.

main {
  display: flex;
  flex-wrap: wrap;
}

.container {
  background: grey;
  margin: 0 10px 20px;
  padding: 10px;
  width: 200px;
}

.top {
  background: red;
}

.middle {
  background: blue;
}

.bottom {
  background: green;
}
<main>
  <div class="container">
    <div class="top">Some text here, Some text here, Some text here</div>
    <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here</div>
    <div class="bottom">And a little here too</div>
  </div>
  <div class="container">
    <div class="top">Some text here, Some text here</div>
    <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here, And some here, And some here, And some here</div>
    <div class="bottom">And a little here too, And a little here too</div>
  </div>
  <div class="container">
    <div class="top">Some text here, Some text here, Some text here, Some text here, Some text here</div>
    <div class="middle">And some here</div>
    <div class="bottom">And a little here too</div>
  </div>
  <div class="container">
    <div class="top">Some text here, Some text here, Some text here</div>
    <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here</div>
    <div class="bottom">And a little here too</div>
  </div>
  <div class="container">
    <div class="top">Some text here, Some text here, Some text here</div>
    <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here</div>
    <div class="bottom">And a little here too</div>
  </div>
  <div class="container">
    <div class="top">Some text here, Some text here, Some text here</div>
    <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here</div>
    <div class="bottom">And a little here too</div>
  </div>
  <div class="container">
    <div class="top">Some text here, Some text here, Some text here</div>
    <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here</div>
    <div class="bottom">And a little here too</div>
  </div>
</main>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
user7409110
  • 289
  • 1
  • 5
  • 14
  • you must align each flex item separately – vsync Mar 03 '17 at 12:15
  • 2
    Flexbox is flexible. As in, it allows your children elements to have different dimensions depending on content. If you want to link children from different parents you'll need to give them rules that disable `flexbox` behavior inside the parents and give them fixed heights. Or you need to change your markup so all items you want related are siblings inside the same parent row. The third option is to link them using `javascript`. – tao Mar 03 '17 at 12:18
  • @AndreiGheorghiu - Yes, this is what I was trying to get away from, i.e. no fixed heights as the content can be variable in height. And I need all of the child elements to appear within it's own parent container (there is an unknown number of containers each time). – user7409110 Mar 03 '17 at 12:24
  • @lavrton duplicate of this: https://stackoverflow.com/q/56711501/8620333 – Temani Afif Jul 17 '20 at 20:05
  • duplicate: https://stackoverflow.com/q/36721216/3597276 – Michael Benjamin Jul 18 '20 at 18:23

3 Answers3

6

Maybe grid with display: contents helps you.

main {
  display: grid;
  
  grid-auto-columns: 200px;
  column-gap: 20px;
}

.container {
  display: contents;
}

.top {
  grid-row: 1;
}

.middle {
  grid-row: 2;
}

.bottom {
  grid-row: 3;
}

https://codepen.io/sunnyone/pen/dyGQYBv

Maybe additional child elements are nesessary if the original .container styles are important.

sunnyone
  • 1,450
  • 2
  • 13
  • 13
-1

Try this, maybe it help you

.container {
  background: grey;
  margin: 0 10px 20px;
  padding: 10px;
  width: 200px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

Live demo - http://codepen.io/anon/pen/oZxaja?editors=1100

grinmax
  • 1,835
  • 1
  • 10
  • 13
  • Sorry, maybe I didn't explain myself very well. I'm looking for the top of each of the red elements to align with each other, the top of each of the blue elements to align with each other and the top of each of the green elements to align with each other. – user7409110 Mar 03 '17 at 12:22
  • @Ash look first container http://codepen.io/anon/pen/XMdxgE?editors=1100 You this mean? – grinmax Mar 03 '17 at 12:29
  • grinmax I've added an image to the initial question above with the desired outcome. Sorry for the confusion. – user7409110 Mar 03 '17 at 12:45
-2

To answer the question directly, I don't think you're going to be able to do what you are trying with your HTML structure and just using CSS/flexbox. I can think of way to do it with JS but what a pain that would be.

If you can, I think you'd have a much easier time restructuring your HTML so that the tops, middles, and bottoms are all in their own rows. You can still have the containers inside the rows to get the look you're going for and create this dynamically, etc, but to get the alignment this seems much easier to me...

.row {
  display: flex;
  flex-direction: row;
}

.container {
  background: grey;
  margin: 0 10px 0px;
  padding: 10px;
  width: 200px;
}

.top {
  background: red;
}

.middle {
  background: blue;
}

.bottom {
  background: green;
}
<main>
  <div class="row">
    <div class="container">
      <div class="top">Some text here, Some text here, Some text here</div>
    </div>
    <div class="container">
      <div class="top">Some text here, Some text here</div>
    </div>
  </div>
  
  <div class="row">
    <div class="container">
      <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here</div>
    </div>
    <div class="container">
      <div class="middle">And some here, And some here, And some here, And some here, And some here, And some here, And some here, And some here, And some here</div>
    </div>
  </div>
  
  <div class="row">
    <div class="container">
      <div class="bottom">And a little here too</div>
    </div>
    <div class="container">
      <div class="bottom">And a little here too, And a little here too</div>
    </div>
  </div>
</main>
MrRobboto
  • 722
  • 3
  • 10
  • Although, looking again I see you need to wrap the containers so that would be a wrench in my solution... – MrRobboto Jul 17 '20 at 19:49
  • If you're rendering dynamically based on data and going to ultimately use JS though, I think it would be easier to measure how many containers can fit the width of the screen and put the three rows inside of another row for each set of containers that can fit in a line. As opposed to trying to align the tops, middle, etc. with JS. – MrRobboto Jul 17 '20 at 19:52