text-overflow ellipsis not working in nested flexbox
Asked Answered
C

5

50

I have a two-column layout created with flexboxes.

In the right column, I have two rows, the first containing a header and the second containing the page content.

Within the header I have three columns, a button, some text, and a button.

I want the buttons to sit on the left and right of the column with the text taking up any additional room.

Finally, I want the text to have white-space:nowrap and text-overflow:ellipsis properties to truncate long titles.

My problem is this: I cannot get the text wrapping to work correctly in a flexbox that is nested in another flexbox, as shown in this fiddle:

http://jsfiddle.net/maxmumford/rb4sk3mz/3/

.container {
  display: flex;
  height: 100vh;
}
.left {
  width: 200px;
  background-color: yellow;
}
.right {
  flex: 1;
  background-color: blue;
  color: white;
}
.header {
  background: red;
  color: white;
  display: flex;
  flex-direction: row;
}
.header .content {
  white-space: nowrap;
  flex: 0 1 auto;
  text-overflow: ellipsis;
  overflow: hidden;
  min-width: 0;
}
.header .buttons {
  background: green;
  flex: 1 0 auto;
}
.header .content:hover {
  white-space: normal;
}
<div class="container">

  <div class="left">
    content left
  </div>
  <div class="right">
    <div class="header">
      <div class="buttons">buttons</div>
      <div class="content">
        This content is really long and should wrap with ellipses, but for some reason it doesn't work when it's nested in a container with display: flex
      </div>
      <div class="buttons">buttons</div>
    </div>
    content right
  </div>

</div>

However, the exact same code works when the header is not nested within a flex box:

http://jsfiddle.net/maxmumford/p7115f2v/1/

.header {
  background: red;
  color: white;
  display: flex;
  flex-direction: row;
}
.header .content {
  white-space: nowrap;
  flex: 0 1 auto;
  text-overflow: ellipsis;
  overflow: hidden;
  min-width: 0;
}
.header .buttons {
  background: green;
  flex: 1 0 auto;
}
<div class="header">
  <div class="buttons">buttons</div>
  <div class="content">
    This content is really long and is wrapped correctly... This content is really long and is wrapped correctly... This content is really long and is wrapped correctly... This content is really long and is wrapped correctly... This content is really long
    and is wrapped correctly... This content is really long and is wrapped correctly... This content is really long and is wrapped correctly...
  </div>
  <div class="buttons">buttons</div>
</div>

How can I achieve what I want in the first fiddle?

Thanks

Catechist answered 3/10, 2016 at 19:20 Comment(0)
D
65

There are two issues in your code preventing the ellipsis from working:

  1. div.right contains div.header, which in turn contains the button and text.

div.right is a flex item in the main container (.container).

By default, a flex item cannot be smaller than the size of its content. The initial setting on flex items is min-width: auto.

This means that the length of your text, which is not wrapping, will set a minimum size for parent flex items. One way to enable flex items to shrink past their content is to set a flex item to min-width: 0.

You've done this already for the .content flex item, but it needs to be set on the .right item, as well.

  1. You've got the .content element set to flex: 0 1 auto.

This tells the flex item to use the size of the content (flex-basis: auto). The text sets the size.

Instead, set the width to 0 and let the flex container distribute space, as necessary. You can do this with flex: 1 1 0, which is the same as flex: 1.

.container {
  display: flex;
  height: 100vh;
}
.left {
  width: 200px;
  background-color: yellow;
}
.right {
  flex: 1;
  background-color: blue;
  color: white;
  min-width: 0;             /* NEW */
}
.header {
  background: red;
  color: white;
  display: flex;
  flex-direction: row;
}
.header .content {
  white-space: nowrap;
  flex: 1;                  /* ADJUSTMENT */
  text-overflow: ellipsis;
  overflow: hidden;
  min-width: 0;
}
.header .buttons {
  background: green;
  flex: 1 0 auto;
}
.header .content:hover {
  white-space: normal;
}
<div class="container">

  <div class="left">
    content left
  </div>
  <div class="right">
    <div class="header">
      <div class="buttons">buttons</div>
      <div class="content">
        This content is really long and should wrap with ellipses, but for some reason it doesn't work when it's nested in a container with display: flex
      </div>
      <div class="buttons">buttons</div>
    </div>
    content right
  </div>

</div>

revised fiddle

Devaney answered 4/10, 2016 at 16:9 Comment(2)
The parent object may also need to be set to min-width: 0px if its size is computed by CSS.Road
If you have a deeply nested flexbox structure (where parents far up the tree also have flex: 1, for example for a sidebar layout) you may need to set min-width: 0 on those parents as well. Learned this the hard way after lots of debugging.Zoila
R
7

The values of :

white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;

Will work only if the content of your element exceeds it's width.

You can set the width of .header .content:

.header .content {
    width: 50%;
}

And it will work as you expect it to:
http://jsfiddle.net/t82pqks4/

Rosenberry answered 3/10, 2016 at 19:40 Comment(3)
Thanks but this makes the header container exceed the width of the page causing a horizontal scroll barCatechist
The two jsfiddles in your question are very different (hover/left-menu/etc). Can you please explain what exactly you are looking for? It's not so clear from your question.Rosenberry
I was missing overflow: hidden. it worked, thanks :)Battista
P
5

Above solution did not work for me in a very nested Flex layout with rows and columns. It kept making my h3 tag wider than the parent because of the

white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

But I accidentally found that adding display: inline-grid; to the parent resolved the problem and applied ellipsis correctly.

I am not sure if it is of help to you but it was for me.

Psychoactive answered 10/5, 2023 at 15:34 Comment(0)
P
0

I had encountered a similar problem but because in my case there were multiple flex-items nested, I found it easier to resolve it by adding another child wrapper inside the last flex-item and having the text inside of that. I made sure not to set display: flex for this new child and added the other three properties white-space, overflow and text-overflow on this child.

Prologize answered 7/12, 2023 at 0:6 Comment(0)
F
-3

I hope this solution helps someone as nothing else I found worked because of how my page was a giant nested combination of flexbox. so min-width 0 didn't work, nothing I tried worked except this.

Inside the flex column that has the copy you want to wrap, you need to do this.

.row {
  display: flex;
}

.col1 {
 position: relative;
 flex: 1 1 70%;
 overflow: hidden;
}

.nested {
  width: 100%;
  position: absolute;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.col2 {
  flex: 1 1 30%;
  padding-left: 1rem;
}
<div class="row">
  <div class="col1">
     <div class="nested">This is my really long copy that will push it out of the screen, and will not respect the elippse no matter what I do!!!</div>
  </div>
  <div class="col2">
    Last Text
  </div>
</div>
Finery answered 22/12, 2020 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.