1

I'm building a column layout in Flexbox using space-between, which looks great if there are three columns, but our web app will sometimes only output two columns, and then the layout breaks as the second column moves to the far-right.

I'd like to achieve a layout where the first and third columns are flush against their respective margins, as they are now, and where the second column remains in place if there is no third column.

I've tried a few different things, with manual padding, but none worked dynamically enough.

CSS:

.events-row {
  display: flex;
  justify-content: space-between;
  .card {
    display: flex;
    flex-direction: column;
    flex-basis: 31.3%;
    position: relative;
    font-size: 1rem;
    .card-img {
      position: relative;
      img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      .series-caption {
        position: absolute;
        top: 0;
        left: 0;
        padding: 5px 15px;
        width: auto;
        font-size: 1em;
        color: white;
        text-transform: uppercase;
      }
    }
    .card-info {
      display: flex;
      flex-direction: column;
      flex-grow: 1;
      flex-shrink: 0;
      position: relative;
      padding: 15px;
      background-color: grey;
      text-align: left;
      font-size: 1.2em;
      color: white;
      h1,
      h2 {
        padding-bottom: 0;
      }
      h2 {
        font-size: 1.5em;
        color: black;
      }
      h3 {
        font-size: 1.1em;
        line-height: 1.5;
      }
      p {
        padding: 15px 0;
        font-size: 0.85em;
        a {
          font-size: 1.1em;
        }
      }
      .button-cont {
        margin-top: auto;
        padding: 30px;
        align-self: center;
        .button {
          display: inline-block;
          padding: 10px 30px;
          font-size: 1em;
        }
      }
    }
    .card-flip-cont {
      height: 603.75px;
      .back,
      .front {
        display: flex;
        flex-direction: column;
      }
      .back {
        .card-info {
          padding: 60px 30px 15px;
          overflow: scroll;
          .close-button {
            position: absolute;
            top: 15px;
            right: 15px;
          }
          .event-perfs {
            padding: 30px 0;
            > h2 {
              font-size: 1.2em;
            }
            .event-perfs-form {
              padding: 15px 0;
              > div {
                &:not(: last-child) {
                  padding-bottom: 15px;
                }
              }
            }
          }
        }
      }
    }
  }
}

HTML:

<div class="events-row">
  <div class="card">
    <div class="card-img four-three-img">
      <a href="#"><img src="http://i.imgur.com/gsnJi.jpg" /></a>
    </div>
    <div class="card-info">
      <h2>Event title</h2>
      <h3>Event date</h3>
      <h3>Event venue</h3>
      <p>
        Cu cum quem eros periculis, volutpat tractatos accommodare eu has, ex singulis assueverit usu.
        <a class="learn-more" href="#">Learn More <span class="chevron right"></span></a>
      </p>
      <div class="button-cont">
        <a class="button blue-button" href="#">Buy Tickets</a>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-img four-three-img">
      <a href="#"><img src="https://img.buzzfeed.com/buzzfeed-static/static/2014-05/enhanced/webdr06/14/7/enhanced-21657-1400066093-5.jpg" /></a>
      <div class="series-caption">Series title</div>
    </div>
    <div class="card-info">
      <h2>Event title</h2>
      <h3>Event date</h3>
      <h3>Event venue</h3>
      <p>
        Cu cum quem eros periculis, volutpat tractatos accommodare eu has, ex singulis assueverit usu.
        <a class="learn-more" href="#">Learn More <span class="chevron right"></span></a>
      </p>
    </div>
  </div>
  <div class="card">
    <div class="card-img four-three-img">
      <a href="#"><img src="https://img.buzzfeed.com/buzzfeed-static/static/2014-05/enhanced/webdr06/14/7/enhanced-6134-1400067964-1.jpg" /></a>
      <div class="series-caption">Series title</div>
    </div>
    <div class="card-info">
      <h2>Event title</h2>
      <h3>Event date</h3>
      <h3>Event venue</h3>
      <p>
        Cu cum quem eros periculis, volutpat tractatos accommodare eu has, ex singulis assueverit usu.
        <a class="learn-more" href="#">Learn More <span class="chevron right"></span></a>
      </p>
    </div>
  </div>
</div>

Demo: CodePen

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Mario Parra
  • 1,504
  • 3
  • 21
  • 46

2 Answers2

1

The simplest way to achieve that layout, using CSS, would be to always keep the space for the third column reserved. In other words, whether the column is there or not, the layout sees it there.

flex-container {
  display: flex;
  justify-content: space-between;
  border: 1px solid gray;
}

flex-item {
  flex-basis: 20%;
  height: 100px;
  margin: 5px;
  background-color: red;
}

[optional] {
  visibility: hidden; /* toggle off when third column needed */
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item optional></flex-item>
</flex-container>

jsFiddle

Here's an explanation of the problem you're having: Center and bottom-align flex items

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
1

If you use the pseudo element ::after on the container, it will work either the third column is rendered or not

body > div {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  border: 1px solid lightgray;
}

body > div::after,
div div {
  flex-basis: calc(30% - 20px);
  height: 100px;
  margin: 10px;
  background-color: red;
}

body > div::after {
  content: '';  
  height: 0;
}

div div:nth-child(3) {
  display: none;
}
<div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div>
  <div></div>
  <div></div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • Thanks! I'm leaning towards this answer to avoid dynamically inserting empty elements. One thing I noticed is that it doesn't work if there are three columns. See http://codepen.io/ourcore/pen/gmYXPY. Do you know how I could resolve this or should I just add the `:after` properties to a class that I dynamically add? – Mario Parra Mar 02 '17 at 23:12
  • @MarioParra Updated my answer. When using 3 or more you need to add `flex-wrap: wrap;` for the row as well ... updated my answer .. and your codepen: http://codepen.io/anon/pen/EWKoXW?editors=1100 – Asons Mar 03 '17 at 05:32
  • That did it. Thanks so much! – Mario Parra Mar 03 '17 at 14:46