Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the behavior of overflow: hidden in a flexbox container

Tags:

html

css

flexbox

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>
like image 421
Question Mcquestioner Avatar asked Jul 12 '16 12:07

Question Mcquestioner


2 Answers

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>
like image 154
Oriol Avatar answered Oct 11 '22 04:10

Oriol


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.

like image 40
Michael Benjamin Avatar answered Oct 11 '22 04:10

Michael Benjamin