Flexbox item multiline text overflow - css

I have flex item with very long string inside, and I want it to be wraped. But it doesn't work.
I set flex 1 1 500px, for instance (flex-basis = 500px) and it should wrap the string with word wrap: break-word
But it doesn't, and only if I set width=500px, it starts to work, so the question is why flex-basis 500px doesn't work and width works?
HTML:
<div class="map-detail-wrapper">
<div class="ad-detail-text">
<span>{{ad.text}}</span>
</div>
</div>
CSS:
.map-detail-wrapper {
display: flex;
flex-wrap: wrap;
}
.ad-detail-text {
flex: 1 1 0%;
width: 500px;
line-height: 20px;
font-size: 14px;
margin: 20px;
border: black;
word-wrap: break-word;
overflow: hidden;
}

In your case you are allowing the item to shrink giving it flex: 1 1 500px which is short for:
flex-grow: 1;
flex-shrink: 1;
flex-basis: 500px;
since the content is less the 500px width and the item is allowed to shrink, it will. To fix that you can set flex: 0 0 500px
In most cases flex-basis is equivalent to width, you can read more about the differences here
For the difference between word-break: break-all and word-wrap: break-word you can read more about it here

Finnally found workaround. You can see it there https://www.w3schools.com/code/tryit.asp?filename=FFPNFOV52YNW
It enough to add
"word-break: break-all;"
and it starting to work even without "width" only with "flex-basis".
But i still wondering why
"word-wrap: break-word" works only with "width",
and to make word wrap only with flex-basis it requires "word-break: break-all;"

Related

max-content flex based child text div shrinks even if enough space available

I am trying to position in-line, aligned to left, some "field-boxes" using CSS flex-box.
A "field-box" is formed from two horizontally adjacent elements:
a text div label
an input element
The label should occupy maximum it's un-wrapped content, but may shrink if there is not enough space up to a min-width (ex. 50px)
The input field has a normal length (ex. 200px) - ideally keep it's width but may also shrink if available space drops, up to a min-width (ex. 100px).
The desired behaviour:
if width(row) >= sum(width(all un-wrapped labels)) + sum(width(input-fields)) -> then the field-boxes are adjacent, aligned left, fully visible, with possible extra space remaining on the right part of the row
else if width(row) >= sum(width(input-fields)) + sum(min-width(labels)) -> then the field-boxes are adjacent, aligned left, with the input fields fully visible and the label fields partially visible (shrinking proportionally), so all row width is occupied
else if width(row) >= sum(min-width(input-fields) + sum(min-width(labels)) -> then the field boxes are adjacent, aligned left, with the labels shrinking to min-width and the input-fields shrinking proportionally to occupy the entire row width
else(row width is less then sum of min-widths of inputs and labels) - TBD either
wrap
scroll
hide extra
Unfortunately I am stuck at first point.
Tried code in snippet and even if the row width is > sum width(elements), the browser shrinks the labels, leaving extra space on the right (on Chrome and Safari on Mac)
I guess having the parent (box) and child (label) having flex-shrink: 1 pushes the label width / max-content to strange dimensions... also used auto and fit-content instead of max-content.
Any ideas how to solve this?
Thank you
<html>
<style>
* {
box-sizing: border-box;
}
.row {
height: 45px;
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
width: 100%;
}
.box {
height: 100%;
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
flex: 0 1 max-content;
}
.label {
height: 100%;
text-overflow: clip;
white-space: nowrap;
margin-left: 5px;
line-height: 41px;
min-width: 50px;
overflow: hidden;
flex: 0 1 max-content;
}
.inputEl {
max-width: 200px;
height: 35px;
margin-left: 5px;
min-width: 100px;
flex: 0 0 auto;
}
</style>
</html>
<body>
<div class="row">
<div class="box">
<div class="label">This is first</div>
<input class="inputEl">
</div>
<div class="box">
<div class="label">This is second</div>
<input class="inputEl">
</div>
<div class="box">
<div class="label">This is third</div>
<input class="inputEl">
</div>
</div>
</body>

Why flex container `flex: 1 0 0px` collapses on Chrome?

On Chrome I encountered Flexbox behaviour I don't understand. When a flex child which is also a flex container has flex: 1 0 0px, it collapses itself and it's contents.
Even though flex-basis is set to 0px, as far as I understand setting flex-grow to 1 (first number in flex shorthand) should make the item grow, when needed.
In my example .bottom-container has height set to 300px. That height is respected on Firefox, but collapsed to 0px on Chrome. Why?
.top-container {
display: flex;
flex-flow: column nowrap;
}
.middle-container {
flex: 1 0 0px;
display: flex;
flex-flow: column nowrap;
}
.bottom-container {
flex: 0 0 auto;
height: 300px;
}
<div class="top-container">
<div class="middle-container">
<div class="bottom-container"></div>
</div>
<div class="middle-container">
<div class="bottom-container"></div>
</div>
</div>
The problem is with the flex-basis component.
When you have flex-basis: 0, Chrome and Firefox compute to flex-basis: 0px.
However, the pixel value breaks your layout in Chrome.
Instead, for cross-browser compatibility, use this:
flex: 1 0 0%
Ok, so here's the logic.
You haven't specified a height of .top-container so it's child elements (.middle-container) cannot grow, because there is no room for them to grow into, despite having flex: 1 0 0 and, therefore, .middle-container elements will always maintain a height of 0.

Flexbox: how to get divs to fill up 100% of the container width without wrapping?

I'm in the process of updating an old inline-block-based grid model I have to a newer Flexbox one I created. Everything has worked fine, apart from one little snag, which has become a bit of a dealbreaker:
I have a bunch of CSS-controlled sliders; so there's a containing wrapper with 100% width, and inside is another div: its width is also 100%, but its white-space is set to nowrap. Using inline-block, this meant that the internal divs (which were also set to 100% width) wouldn't be bound by their parents' constraints and wrap onto the next line - they'd just carry on flowing out of the box. This is exactly what I wanted. However, I cannot get this to work at all with flexbox. For reference, here's an image:
And for reference, here's a jsFiddle of the thing working with inline-block: http://jsfiddle.net/5zzvqx4b/
...and not working with Flexbox: http://jsfiddle.net/5zzvqx4b/1/
I've tried all kinds of variations with flex, flex-basis, flex-wrap, flex-grow, etc. but for the life of me I can't get this to work.
Note that I can force it to do what I want in a hacky, inflexible way by setting the .boxcontainer width to 200%. That works for this single example, but in some cases I won't know beforehand how many child boxes there will be, and I'd rather not resort to inline styling on each element if possible.
To prevent the flex items from shrinking, set the flex shrink factor to 0:
The flex shrink factor determines how much the flex item will
shrink relative to the rest of the flex items in the flex
container when negative free space is distributed. When omitted, it is
set to 1.
.boxcontainer .box {
flex-shrink: 0;
}
* {
box-sizing: border-box;
}
.wrapper {
width: 200px;
background-color: #EEEEEE;
border: 2px solid #DDDDDD;
padding: 1rem;
}
.boxcontainer {
position: relative;
left: 0;
border: 2px solid #BDC3C7;
transition: all 0.4s ease;
display: flex;
}
.boxcontainer .box {
width: 100%;
padding: 1rem;
flex-shrink: 0;
}
.boxcontainer .box:first-child {
background-color: #F47983;
}
.boxcontainer .box:nth-child(2) {
background-color: #FABCC1;
}
#slidetrigger:checked ~ .wrapper .boxcontainer {
left: -100%;
}
#overflowtrigger:checked ~ .wrapper {
overflow: hidden;
}
<input type="checkbox" id="overflowtrigger" />
<label for="overflowtrigger">Hide overflow</label><br />
<input type="checkbox" id="slidetrigger" />
<label for="slidetrigger">Slide!</label>
<div class="wrapper">
<div class="boxcontainer">
<div class="box">
First bunch of content.
</div>
<div class="box">
Second load of content.
</div>
</div>
</div>
You can use the shorthand flex property and set it to
flex: 0 0 100%;
That's flex-grow, flex-shrink, and flex-basis in one line. Flex shrink was described above, flex grow is the opposite, and flex basis is the size of the container.
In my case, just using flex-shrink: 0 didn't work. But adding flex-grow: 1 to it worked.
.item {
flex-shrink: 0;
flex-grow: 1;
}
Set the flex-direction: column
You're trying to stack the items in a column rather than a row.
{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

flex-basis not working as expected

As i understand flex-basis is responsible for deciding the size of an element.
In the example below, I am trying to size all boxes equally to 100px.
Just using flex-basis is not achieving the effect.
.each_box {
-webkit-flex-grow: 0;
-webkit-flex-shrink: 0;
-webkit-flex-basis: 100px;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100px;
background-color: yellow;
height: 50px;
border: 1px solid black;
}
Plnkr here: http://plnkr.co/edit/LvrrzHWIw1tPGwK05bCU
I found I had to use min-width as well as flex-basis in Chrome. I'm not sure if I had another problem that caused this.
.flex-container {
display: flex;
width: 100%;
}
.flex-child {
flex-basis: 50%;
min-width: 50%;
}
Be sure to also add: flex-wrap: wrap; because the default value nowrap in order to fit everything in one line can affect the size of the elements (eg: width, flex-basis, etc..).
The flex-grow, flex-shrink, flex-basis properties only have an effect on elements in a flex container -- i.e. elements whose parent has display:flex.
You need to put your each_box divs directly inside of a display:flex element for them to honor their flex-related properties.
Specifically, your markup looks like this (from right clicking one of the yellow divs + hitting "inspect" in Firefox):
<div class="container">
<!-- ngRepeat: stock in stockList -->
<div class="ng-scope" ng-repeat="stock in stockList">
<div class="each_box ng-binding">
0-FB/100
You've got container styled as display:flex, but that does no good for your each_box elements, because they're grandchildren, separated from the flex container by the display:block ng-scope.
So you either need to get rid of the ng-scope wrapper, or make it also have display:flex.
Add a width: width:100px;
flex-basis gives a default proportion, which will then grow or shrink.
All works for me:
.flex-child { width:0; }
AND
.flex-child { min-width:0; }
AND
.flex-child { flex-shrink:0; } /* no scrollbars inside */

Fill remaining horizontal space (or max-width) AND wrap on min-width

#fit and #wrap illustrate two different behaviors that I want to have for one element depending on the situation. The element should work like #fit if there is room, but should work like #wrap if there is not enough room.
http://jsfiddle.net/benstenson/dN8VJ/
<div id="print">
Printable
</div>
<div id="fit">
Looks good on same line
</div>
<div id="wrap">
Looks good on new line
</div>
css
body{overflow:hidden;padding:1em;}
div
{
/*display:inline-block;*/
float:left;
height:1in;
margin:.5em;text-align:center;line-height:1in;
white-space:nowrap;box-shadow:0 0 .5em gray;
}
#print
{
width:5in;
background-color:black; color:white;
}
#fit
{
/* when on same line
Size to min-width
OR fill remaining space
(like flexible box style).
Either way is fine.
*/
min-width:3in;
background-color:gold;
}
#wrap
{
/* when wrapped to next line */
/* fill 100% OR to max width */
width:100%;
min-width:3in;
max-width:5in;
background-color:orange;
}
What you're looking for is Flexbox, but most browsers that support Flexbox don't support wrapping. The ones that do are IE10, Chrome, and Opera.
http://codepen.io/cimmanon/pen/lqrGB
<div class="container">
<div id="print">
Printable
</div>
<div id="either">
Looks good on either line
</div>
</div>
.container {
display: -ms-flexbox;
display: -webkit-flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
#supports (flex-wrap: wrap) {
.container {
display: flex;
}
}
.container div {
height: 1in;
margin: .5em;
text-align: center;
line-height: 1in;
white-space: nowrap;
box-shadow: 0 0 .5em gray;
}
#print {
/*-webkit-flex: 1 5in;
-ms-flex: 1 5in;
flex: 1 5in;*/
width: 5in;
background-color: black;
color: white;
}
#either {
-webkit-flex: 1 3in;
-ms-flex: 1 3in;
flex: 1 3in;
max-width: 5in;
background-color: gold;
}
Assuming I've understood your question correctly, I think you can achieve what you want with inline-block.
You'll need to put your content in a paragraph inside another div, like this:
<div class="wrap-or-fit">
<p>This is where your content goes.</p>
</div>
Then just set the min-width and max-width properties on the paragraph, as well as display:inline-block.
.wrap-or-fit > p {
max-width:5in;
min-width:3in;
display:inline-block;
...
}
If the content fits on a single line less than 3 inches wide, the container will expand to be at least 3 inches. If the content is wider than 5 inches, it is forced to wrap within a container of exactly 5 inches.
If the content is between 3 and 5 inches, the container width matches the content width. I'm not sure if that is what you wanted, but that may be the best you can do.
You can see an expanded example showing both narrow and wide content samples, and styling that more closely matching your original example in this codepen.

Resources