2

Not quite sure how to word this question. What I'm trying to do is allow for a layout where there is a label/data pair stacked in columns. So markup might be:

<div>
    <div class="label">hello</div>
    <div class="data">world</div>
<div>

And I want multiples of those in equal width columns so I use flexbox and end up with something like this:

hello        hello        hello

world        world        world

This gives me a nice visual with easy accessibility as the label/pairs are read together in markup flow.

Works fine. Now, the snag: the labels can get quite long. So I end up with something like this:

hello        hello this   hello
             is a really
world        long label   world      

             world     

And what I really want is this:

hello        hello this   hello
             is a really
             long label              

world        world        world     

Is this doable with flexbox? I attempted to come up with something but it's not quite there:

http://jsfiddle.net/0Lfqaj82

My gut says no, this can't be done, because each individual row in each column has no understanding of the height of the rows in an adjacent column. But as I'm surprised with each new bit of flexbox I learn, I thought I'd ask.

I realize I could make this work by putting all the labels in one row of columns, and all the data in a separate row of columns, and then perhaps use some ARIA attributes to tie them together for accessibility. Perhaps that's the best solution?

DA.
  • 39,848
  • 49
  • 150
  • 213
  • with your structure it cannot be done (at least in a clean way) as you have many nested div. If you are able to bring all the element at the same level you can do it – Temani Afif Aug 07 '19 at 21:48

2 Answers2

3

Make two adjustments to make the layout work.

Add this to your code:

.flex-rows {
   flex: 1; /* gives this container the height of its parent */
}

.row-flex:last-child {
   margin-top: auto; /* spaces siblings away to the extremes;
                       .row-flex:first-child { margin-bottom: auto } would also work;
                        and so would justify-content: space-between on the container
                        (which would save you from having to create this new rule; */
}

In the revised code below, I've commented out what appear to be unnecessary rules.

.flex-cols {
  display: flex;
  /* width: 100%; */
  /* flex-direction: row; */
}

.col-flex {
  display: flex;
  flex: 1;
  /* flex-basis: 100%; */
  flex-direction: column;
  margin-right: 20px;
  border: 1px solid green;
  padding: 5px;
}

.flex-rows {
  flex: 1; /* ADDITION #1 */
  display: flex;
  /* width: 100%; */
  flex-direction: column;
}

.row-flex {
  border: 1px solid red;
  display: flex;
  /* flex: 1; */
  /* flex-basis: 100%; */
  flex-direction: column;
  margin-bottom: 20px;
}

.row-flex:last-child {
    margin-top: auto; /* ADDITION #2 */
}
<div class="flex-cols">
  <div class="col-flex">
    <div class="flex-rows">
      <div class="row-flex">
        Hello
      </div>
      <div class="row-flex">
        World
      </div>
    </div>
  </div>
  <div class="col-flex">
    <div class="flex-rows">
      <div class="row-flex">
        Hello, hello, hello! This is a bunch of extra text to explain what should happen. Ideally, this will take up as much room as needed, and the div below will take up an equal amount to force a vertical 50/50 split.
      </div>
      <div class="row-flex">
        World
      </div>
    </div>
  </div>
   <div class="col-flex">
    <div class="flex-rows">
      <div class="row-flex">
        Hello
      </div>
      <div class="row-flex">
        World
      </div>
    </div>
  </div>
</div>

jsFiddle demo

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • That works! And thanks for the nicely commented example. I'm not exactly sure I understand WHY it works...it appears using `margin: auto` automatically adds space as needed to space things apart? – DA. Aug 08 '19 at 18:30
  • You're welcome. [`auto` margins have a special function in flex and grid layouts.](https://stackoverflow.com/a/33856609/3597276) – Michael Benjamin Aug 08 '19 at 18:33
0

HTML

<div class="flex-container">
<div class="grid-container">

  <div class="label">hello fdafdsa fdsafdsafdsafdsa fdsaf dsafdsafds afdsa</div>

  <div class="data">world</div>
</div>
<div class="grid-container">

  <div class="label">hello</div>

  <div class="data">world</div>
</div>
<div class="grid-container">

  <div class="label">hello</div>

  <div class="data">world</div>
</div>
</div>

CSS

.grid-container{
  display: grid;
  width: 100px;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr 1fr;
}
.flex-container{
  display:flex;
  flex-direction:row;
  flex-wrap:wrap;
}

If you structure it this way you will be able to create the desired effect.

https://jsfiddle.net/xzq8mvju/2/

Vch Cvh Hvc
  • 226
  • 1
  • 8