How to keep a flex item from overflowing due to its text?

Google ChromeFlexboxCss

Google Chrome Problem Overview


I have the following layout in mind for a list. Each list item is represented by two columns. The second column should take up all available space, but it should be anchored to the right with its minimum size if the first column is taking up too much space. The first column should then show an ellipsis.

The problem is happening in that last case. When the first column consists of too much text, instead of showing an ellipsis, it stretches itself out of the flexbox causing an horizontal scrollbar to appear, and the second column is not anchored to the right.

I would like to have it rendered like this (mockup):

Expected rendering

How can I achieve that?

This is sample fiddle .

.container {
    display: -webkit-flex;
}

div {
    white-space: nowrap;
    text-overflow: ellipsis;
}

.container > div:last-child {
    -webkit-flex: 1;
    background: red;
}

<!-- a small first column; the second column is taking up space as expected -->
<div class="container">
    <div>foo barfoo bar</div>
    <div>foo bar</div>
</div>

<!-- a large first column; the first column is overflowing out of the flexbox container -->
<div class="container">
    <div>foo barfoo barfoo barfoo barfoo barfoo barfoo bar
    foo barfoo barfoo barfoo barfoo barfoo barfoo bar
    foo barfoo barfoo barfoo barfoo barfoo barfoo bar</div>
    <div>foo bar</div>
</div>

Google Chrome Solutions


Solution 1 - Google Chrome

UPDATE

Adding code that works:

.container {
    display: -webkit-flex; 
}

.container>div:first-child{
    white-space:nowrap;
   -webkit-order:1;
   -webkit-flex: 0 1 auto; /*important*/
    text-overflow: ellipsis;
    overflow:hidden;
    min-width:0; /* new algorithm overrides the width calculation */
}

.container > div:last-child {
    -webkit-flex: 1;
    -webkit-order:2;
    background: red;
    -webkit-flex:1 0 auto; /*important*/
}
.container > div:first-child:hover{
    white-space:normal;
}

<div class="container">
    <div>foo barfoo bar</div>
    <div>foo bar</div>
</div>

<div class="container">
        <div>foo barfoo barfoo barfoo barfoo barfoo barfoo bar
        foo barfoo barfoo barfoo barfoo barfoo barfoo bar
        foo barfoo barfoo barfoo barfoo barfoo barfoo bar</div>
    <div>foo bar</div>
</div>
<div class="container">
    <div>foo barfoo bar</div>
    <div>foo bar</div>
</div>

<div class="container">
        <div>foo barfoo barfoo barfoo barfoo barfoo barfoo bar
        foo barfoo barfoo barfoo barfoo barfoo barfoo bar
        foo barfoo barfoo barfoo barfoo barfoo barfoo bar</div>
    <div>foo bar</div>
</div><div class="container">
    <div>foo barfoo bar</div>
    <div>foo bar</div>
</div>

Original answer / explanation.

W3C specification says, "By default, flex items won't shrink below their minimum content size (the length of the longest word or fixed-size element). To change this, set the ‘min-width’ or ‘min-height’ property."

If we follow this line of reasoning, I believe the bug has been removed from Canary, not the other way round.

Check as soon as I put min-width to 0, it works in Canary.

So bug was in older implementations, and canary removes that bug.

This example is working in canary. http://jsfiddle.net/iamanubhavsaini/zWtBu/

I used Google Chrome Version 23.0.1245.0 canary.

Solution 2 - Google Chrome

You can set the preferred size of the child by setting the third value of the flex property to auto, like so:

flex: 1 0 auto;

This is shorthand for setting the flex-basis property.

(Example)

As noted in the comments however, this doesn't seem to work in Chrome Canary, although I'm not sure why.

Solution 3 - Google Chrome

Update: This is not the answer. It solves different problem, and it was a step in finding the real answer. So I am keeping it for the historical reasons. Please don't vote on it.

I believe this is your answer: http://jsfiddle.net/iamanubhavsaini/zWtBu/2/

enter image description here

refer W3C

for the first element

-webkit-flex: 0 1 auto; /* important to note */

and for the second element

-webkit-flex:1 0 auto; /* important to note */

are the properties and values that do the trick.

Read more at http://www.w3.org/TR/2012/WD-css3-flexbox-20120612/#flex


and this is how you reverse the order: http://jsfiddle.net/iamanubhavsaini/zWtBu/3/

and this one with the predefined minimum width of the red-backgrounded-thingy: http://jsfiddle.net/iamanubhavsaini/zWtBu/1/

Solution 4 - Google Chrome

Update: This is not the answer. It solves different problem, and it was a step in finding the real answer. So I am keeping it for the historical reasons. Please don't vote on it.

EDIT 2: This answer doesn't solve the problem. There is a subtle difference between target of the question and the answer.

First of all, text-overflow:ellipsis works with overflow:hidden. Actually, it works with anything other than overflow:visible .Ref

Then, iterate through:

http://jsfiddle.net/iamanubhavsaini/QCLjt/8/

Here, I have put overflow and max-width properties. max-width:60%; and overflow:hidden is what makes things appear as you intended, as hidden stops the text from displaying and 60% actually creates the box of definite size in case of too much text data.

Then, if you are really interested in flex box model here's how things pan out via -webkit-order.

http://jsfiddle.net/iamanubhavsaini/QCLjt/9/

--code--

<div class="container">
    <div>foo barfoo bar</div>
    <div>foo bar</div>
</div>

<div class="container">
        <div>foo barfoo barfoo barfoo barfoo barfoo barfoo bar
        foo barfoo barfoo barfoo barfoo barfoo barfoo bar
        foo barfoo barfoo barfoo barfoo barfoo barfoo bar</div>
    <div>foo bar</div>
</div>

​concerned CSS

.container {
    display: -webkit-flex;
}

div {
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow:hidden;
}
.container>div:first-child{
   -webkit-order:1;
        -webkit-flex: 1;
}
.container > div:last-child {
    -webkit-flex: 1;
    -webkit-order:2;
    background: red;
}

​-- There is no width and still it works. And this is what I see.

enter image description here

--after comment

-webkit-order:N; is the what we will be using after 2+ years instead of float:---; and many more hacks(if W3C stays on this course and also if every browser vendor follow)

here, order is 1 for the left div and 2 for the right div. thus, they are Left-Right.

http://jsfiddle.net/iamanubhavsaini/QCLjt/10/

same thing here, but only if you are looking for Right-Left, just change the order of the things as div>first-child { -webkit-order:2; } div>last-child{-webkit-order:1;}

NOTE: this -webkit-flex way of doing things obviously renders this code useless on other engines. For, reuse of code, on multiple browser engines floating should be used.

below are some JS examples; that doesn't answer the question -after comment

I think this answers your question and many more to come, there are some other ways and different solutions but not exactly the solution for this question. http://jsfiddle.net/iamanubhavsaini/vtaY8/1/ http://jsfiddle.net/iamanubhavsaini/9z3Qr/3/ http://jsfiddle.net/iamanubhavsaini/33v8g/4/ http://jsfiddle.net/iamanubhavsaini/33v8g/1/

Solution 5 - Google Chrome

for mozilla you should add "min-width: 1px;"

Solution 6 - Google Chrome

This example really helped me: http://jsfiddle.net/laukstein/LLNsV/

container {
    display: -webkit-flex;
    -webkit-flex-direction: row;
    padding: 0;
    white-space: nowrap;
}

.container>div {
    overflow: hidden;
    display: inline-block;
    -webkit-flex: 1;
    min-width: 0;
    text-overflow: ellipsis;
    -moz-box-sizing: border-box;
         box-sizing: border-box;
}

Solution 7 - Google Chrome

You should make the container position: relative and the child position: absolute.

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
QuestionpimvdbView Question on Stackoverflow
Solution 1 - Google Chromeuser900360View Answer on Stackoverflow
Solution 2 - Google ChromeMarcus StadeView Answer on Stackoverflow
Solution 3 - Google Chromeuser900360View Answer on Stackoverflow
Solution 4 - Google Chromeuser900360View Answer on Stackoverflow
Solution 5 - Google ChromegokselView Answer on Stackoverflow
Solution 6 - Google ChromeCon AntonakosView Answer on Stackoverflow
Solution 7 - Google ChromeRadu BreharView Answer on Stackoverflow