Prevent a child element from overflowing its parent in flexbox

HtmlCssFlexbox

Html Problem Overview


I'm working on a web app that shows a large grid of cards, the height of which is inherently variable.

In the interests of aesthetics, we were using jQuery's .matchHeight() to equalise the height of cards within each row.

The performance of that didn't scale well, so today I've been migrating to a flex-box based solution which is so much faster.

However, I've lost a behaviour - the content of the card header should be truncated with an ellipsis if it won't fit.

Goals:

  1. 3 columns
  2. Column widths vary to fill parent
  3. Constant spacing between columns
  4. Heights equalised within a row

How do I arrange for the container size to be respected and the text-overflow: ellipsis; and white-space: nowrap; to be honoured?

(No jQuery tag as we're moving away from that)

My solution in it's current form, which achieves all of my goals apart from the truncation:

https://codepen.io/anon/pen/QvqZYY

#container { 
                display: flex; 
                flex-direction: row; 
                flex-wrap: wrap; 
                
                justify-content: flex-start;    /* Bias cards to stack from left edge       */ 
                align-items: stretch;           /* Within a row, all cards the same height  */ 
                
                border: thin solid gray; 
            } 
            .card-wrapper { 
                width: 33.33%; 
                display: flex; 
                background: #e0e0ff; 
            } 
            .card { 
                flex-grow: 1; 
                margin: 7px; 
                display: flex; 
                flex-direction: column; 
                border: thin solid gray; 
                background: #e0ffff; 
            } 
            .card div { 
                border: thin solid gray; 
            } 
            .card div:nth-child(1) { 
                white-space: nowrap; 
                text-overflow: ellipsis; 
            } 
            .card div:nth-child(2) { 
                flex-grow: 2; 
            } 

<div id="container"> 
            <div class="card-wrapper"> 
                <div class="card"> 
                    <div>Title</div> 
                    <div>Multiline<br/>Body</div> 
                    <div>Footer</div> 
                </div> 
            </div> 
            <div class="card-wrapper"><div class="card"><div>Really long rambling title that pushes beyond the bounds of the container, unless your screen is really, really wide</div><div>Body</div><div>Footer</div></div></div> 
            <div class="card-wrapper"><div class="card"><div>Title</div><div>Body</div><div>Footer</div></div></div> 
            <div class="card-wrapper"><div class="card"><div>Title</div><div>Body</div><div>Footer</div></div></div> 
            <div class="card-wrapper"><div class="card"><div>Title</div><div>Body</div><div>Footer</div></div></div> 
        </div> 

Html Solutions


Solution 1 - Html

An initial setting on flex items is min-width: auto. This means that a flex item, by default, cannot be smaller than the size of its content.

Therefore, text-overflow: ellipsis cannot work because a flex item will simply expand, rather than permit an overflow. (Scroll bars will not render either, for the same reason.)

To override this behavior, use min-width: 0 or overflow: hidden. More details.

#container {
  display: flex;
  flex-wrap: wrap;
  border: thin solid gray;
}

.card-wrapper {
  width: 33.33%;
  display: flex;
  background: #e0e0ff;
}

.card {
  flex-grow: 1;
  margin: 7px;
  display: flex;
  flex-direction: column;
  border: thin solid gray;
  background: #e0ffff;
  overflow: hidden;        /* NEW */
}

.card div {
  border: thin solid gray;
}

.card div:nth-child(1) {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;        /* NEW */
}

.card div:nth-child(2) {
  flex-grow: 2;
}

<div id="container">
  <div class="card-wrapper">
    <div class="card">
      <div>Title</div>
      <div>Multiline<br/>Body</div>
      <div>Footer</div>
    </div>
  </div>
  <div class="card-wrapper">
    <div class="card">
      <div>Really long rambling title that pushes beyond the bounds of the container, unless your screen is really, really wide</div>
      <div>Body</div>
      <div>Footer</div>
    </div>
  </div>
  <div class="card-wrapper">
    <div class="card">
      <div>Title</div>
      <div>Body</div>
      <div>Footer</div>
    </div>
  </div>
  <div class="card-wrapper">
    <div class="card">
      <div>Title</div>
      <div>Body</div>
      <div>Footer</div>
    </div>
  </div>
  <div class="card-wrapper">
    <div class="card">
      <div>Title</div>
      <div>Body</div>
      <div>Footer</div>
    </div>
  </div>
</div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChrisView Question on Stackoverflow
Solution 1 - HtmlMichael BenjaminView Answer on Stackoverflow