2

I have a flexbox layout in my app similar to the snippet below, a set of lis with three divs in each

.container {
  width: 500px;
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
}
li {
  border: solid 1px black;
  flex: 1;
}
.title {
  border: solid 1px red;
  margin-bottom: 1em;
}
.content {
  border: solid 1px yellow;
  margin-bottom: 1em;
}
.footer {
  border: solid 1px blue;
}
<div class="container">

  <ul>
    <li>
      <div class="title">
        Blah Blah Blah Blah Blah Blah
      </div>
      <div class="content">
        Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
      </div>
      <div class="footer">
        Some other stuff here
      </div>
    </li>
    <li>
      <div class="title">
        Blah Blah Blah Blah Blah Blah
      </div>
      <div class="content">
        Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
      </div>
      <div class="footer">
        Some other stuff here
      </div>
    </li>
    <li>
      <div class="title">
        Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
      </div>
      <div class="content">
        Blah Blah Blah Blah Blah Blah Blah Blah
      </div>
      <div class="footer">
        Some other stuff here
      </div>
    </li>
  </ul>
</div>

I'm looking to have the children divs start at the same level across the times, e.g. the yellow div tops are equal, and the blue div tops are equal. Previously I've done this by making the children divs absolute positioned, and then have them be fixed height, with fixed tops. However, doing this, I have to set the heights based on the guessed maximum size of the text they will contain, which, when combined with the page being responsive (There is single breakpoint where it goes from side by side columns to a carousel), this can lead to a lot of empty space in the columns.

Most examples I've found (as I apparently don't really know the right terms to google this...) involve either Javascript, or rearranging the markup to have the rows at the top of the hierarchy, instead of the columns. I would like to stick with columns, they're set up to handle the cases of 1, 2, or 3 columns, and also serve as a carousel on small devices.

Am I missing how to do this, or am I stuck with Javascript?

Matt Sieker
  • 9,349
  • 2
  • 25
  • 43

2 Answers2

1

You're looking for display:flex-box. Here is some documentation: https://css-tricks.com/snippets/css/a-guide-to-flexbox/.

I have had a go at your current situation, one thing to point out is you're going to need to use both flex directions (row & column).

Another would be if you're using borders and trying to get boxes to align along one row you will need to introduce box-sizing:border-box (includes borders and padding into the declared width). I have also used a calculation on the width of your columns to use the maximum amount of space available in the row reducing any guess-work.

You can apply this to your needs:

        .container * {
            box-sizing: border-box;
        }
            .container {
                width: 500px;
            }
                ul {
                    list-style: none;
                    margin: 0;
                    padding: 0;
                    display: -webkit-box;
                    display: -moz-box;
                    display: -ms-flexbox;
                    display: -webkit-flex;
                    display: flex;
                    -webkit-flex-wrap: wrap;
                    flex-wrap: wrap;
                    flex-direction: row;
                    align-items: stretch;
                    justify-content: center;
                }
                    li {
                        width: calc(100% / 3);
                        border: solid 1px black;
                        box-sizing: border-box;
                        display: -webkit-box;
                        display: -moz-box;
                        display: -ms-flexbox;
                        display: -webkit-flex;
                        display: flex;
                        -webkit-flex-wrap: wrap;
                        flex-wrap: wrap;
                        flex-direction: column;
                        align-items: center;
                        justify-content: space-between;
                    }
                        li > div {
                            width: 100%;
                            padding: 0;
                            margin: 0;
                        }
                        li > div + div {
                            margin-top: 20px;
                        }
                        .title {
                            border: solid 1px red;
                        }
                        .content {
                            border: solid 1px yellow;
                        }
                        .footer {
                            border: solid 1px blue;
                        }
    <div class="container">
        <ul>
            <li>
                <div class="title">
                    Blah Blah Blah Blah Blah Blah
                </div>
                <div class="content">
                    Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
                </div>
                <div class="footer">
                    Some other stuff here
                </div>
            </li>
            <li>
                <div class="title">
                    Blah Blah Blah Blah Blah Blah
                </div>
                <div class="content">
                    Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
                </div>
                <div class="footer">
                    Some other stuff here
                </div>
            </li>
            <li>
                <div class="title">
                    Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
                </div>
                <div class="content">
                    Blah Blah Blah Blah Blah Blah Blah Blah
                </div>
                <div class="footer">
                    Some other stuff here
                </div>
            </li>
        </ul>
    </div>
halfer
  • 19,824
  • 17
  • 99
  • 186
Jason Is My Name
  • 929
  • 2
  • 14
  • 38
0

If you change your HTML markup to this (remove ul li) you could do this with Flexbox. You can set flex: 0 0 33% on each item and flex-wrap: wrap so when flexbox wrap items to new row it will keep same height of items in each row. You then need to adjust order of elements to column with nth-child() selector.

* {
  box-sizing: border-box;
}
.container {
  width: 500px;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
}
div > div {
  flex: 0 0 33%;
}
div > div:nth-child(3n-2) {
  order: 1;
}
div > div:nth-child(3n-1) {
  order: 2;
}
div > div:nth-child(3n) {
  order: 3;
}
.title {
  border: solid 1px red;
  margin-bottom: 1em;
}
.content {
  border: solid 1px yellow;
  margin-bottom: 1em;
}
.footer {
  border: solid 1px blue;
}
<div class="container">
  <div class="title">
    Blah Blah Blah Blah Blah Blah
  </div>
  <div class="content">
    Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
  </div>
  <div class="footer">
    Some other stuff here
  </div>

  <div class="title">
    Blah Blah Blah Blah Blah Blah
  </div>
  <div class="content">
    Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
  </div>
  <div class="footer">
    Some other stuff here
  </div>
  <div class="title">
    Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah Blah
  </div>
  <div class="content">
    Blah Blah Blah Blah Blah Blah Blah Blah
  </div>
  <div class="footer">
    Some other stuff here
  </div>
</div>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176