7

I've been having a few issues with flex boxes and having them span out of their container as the text/content grows, and only applying ellipses when a specified max-width of the container is reached.

This isn't ideal because the parent container can shrink to x pixels and the text just forces it to grow to the max-width which I do not want.

Looking at this fiddle, if I remove overflow: hidden from child1 and apply it to main, the text will just be cut off.

If I remove overflow: hidden from main and apply it to child1, the behaviour I want is achieved.

If I remove overflow: hidden from both of them, the container and text just go on forever.

I just want to know why applying overflow: hidden to child1 produces the desired behaviour. Shouldn't the text just cut off as it did with overflow on main?

.main {
  display: flex;
  border: 1px solid black;
  height: 200px;
  padding: 10px;
  //overflow: hidden;

}
.child1 {
  display: flex;
  border: 1px solid red;
  height: 100px;
  overflow: hidden;
}
.child2 {
  flex: 1 1 auto;
  text-align: center;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
<div class="main">
  <div class="child1">
    <div class="child2">
      Lots of words Lots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of
    </div>
  </div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 2
    When you remove overflow from child1 and apply it to main you will notice that child1 width will now be larger than main. This appears to be due to child2 (lots of text) pushing the width (since there is no longer an overflow). Child1 is now being cut by main but child2 has nothing preventing his expansion – kriddy800 Jul 12 '16 at 12:34
  • Related: [How can I get FF 33.x Flexbox behavior in FF 34.x?](http://stackoverflow.com/q/26895349/1529630) – Oriol Jul 12 '16 at 22:44

2 Answers2

13

That's because Flexbox introduces a new initial value for min-width and min-height: auto.

When you have the initial overflow: visible, min-width: auto computes to the width of the contents of the flex item (see the exact rules).

But when you use a different overflow, min-width: auto will compute to 0.

In your case, .child1 is a flex item. So by default it will be at least as wide as its contents. It can even overflow its container, in that case .main's overflow will be taken into account.

But if you want to prevent .main from growing too much, you can

  • Use a non-visible overflow, as you observed. This will make min-width: auto compute to 0.

    .main {
      display: flex;
      border: 1px solid black;
      height: 200px;
      padding: 10px;
    }
    .child1 {
      overflow: hidden;
      display: flex;
      border: 1px solid red;
      height: 100px;
    }
    .child2 {
      flex: 1 1 auto;
      text-align: center;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }
    <div class="main">
      <div class="child1">
        <div class="child2">
          Lots of words Lots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of
        </div>
      </div>
    </div>
  • Don't make .child a flex item. This will make min-width: auto compute to 0.

    .main {
      border: 1px solid black;
      height: 200px;
      padding: 10px;
    }
    .child1 {
      display: flex;
      border: 1px solid red;
      height: 100px;
    }
    .child2 {
      flex: 1 1 auto;
      text-align: center;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }
    <div class="main">
      <div class="child1">
        <div class="child2">
          Lots of words Lots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of
        </div>
      </div>
    </div>
  • Set min-width: 0 manually

    .main {
      display: flex;
      border: 1px solid black;
      height: 200px;
      padding: 10px;
    }
    .child1 {
      min-width: 0;
      display: flex;
      border: 1px solid red;
      height: 100px;
    }
    .child2 {
      flex: 1 1 auto;
      text-align: center;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }
    <div class="main">
      <div class="child1">
        <div class="child2">
          Lots of words Lots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of wordsLots of
        </div>
      </div>
    </div>
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • thank you SO MUCH. i was going crazy trying to figure out why changing `overflow` seemed to have repercussions on the height of the flex item – Frank Jun 03 '21 at 20:41
  • **Thank you very much!** I just discovered that `overflow: hidden;` has a magical effect on a flex item's width, and then I found your explanation that totally answered my question. – ipid Jun 09 '22 at 03:54
3

When you apply overflow: hidden to .main, this clips .child1 but not .child2 (the div with text).

So .child2 overflows .main because there is no overflow: hidden on .child1 (demo).

To understand this better, try overflow: scroll on .main instead of hidden.

When you use overflow: hidden on .child1, this clips .child2.

Now the width of .child2 is limited, and ellipsis works as intended (demo).

Again, this can be illustrated more clearly with overflow: scroll on .main.

Also keep in mind, the overflow property applies only to content of a block container.

From the spec:

11.1.1 Overflow: the overflow property

This property specifies whether content of a block container element is clipped when it overflows the element's box. It affects the clipping of all of the element's content except any descendant elements (and their respective content and descendants) whose containing block is the viewport or an ancestor of the element.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Just a quick question, if I change the markup to this https://jsfiddle.net/pyefqang/8/ with `child2` now just being a block with a ridiculous width, why is it bound within child1? shouldn't it still span to a crazy width but clipped off when it reaches the edge of `child1` instead of being cound by it – Question Mcquestioner Jul 13 '16 at 07:02
  • 1
    Because (1) There is no content. As stated in the spec (see my answer), the `overflow` property applies only to content, and (2) You need to add `white-space: nowrap`. The initial value of the `white-space` property is `normal`, which means content is allow to wrap. https://jsfiddle.net/pyefqang/9/ – Michael Benjamin Jul 13 '16 at 12:10