Make flex container expand and overflow its container - html

How do I make a flex parent with a nowrap flex-wrap expand to fit its content even if that means overflowing whatever is wrapping the parent?
Basically, the content has a min-width, I want the flex parent not to shrink more than the space all the flex items need.
Here is a JSFiddle https://jsfiddle.net/lazamar/odat477r/
.wrapper {
background-color: yellowgreen;
display: block;
padding: 10px;
max-width: 180px;
}
.parent {
display: flex;
flex-flow: row nowrap;
background-color: yellow;
}
.child {
display: block;
background-color: orange;
margin: 10px;
min-width: 50px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
</div>
</div>

The answer is what t1m0n said. Use display: inline-flex instead of display: flex for the parent.
.wrapper {
background-color: yellowgreen;
display: block;
padding: 10px;
max-width: 180px;
}
.parent {
display: inline-flex; /* -- only change --*/
flex-flow: row nowrap;
background-color: yellow;
}
.child {
display: block;
background-color: orange;
margin: 10px;
min-width: 50px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
</div>
</div>

Using display: inline-flex instead of display: flex is your best bet.
If, for any reason, that's not an option, use CSS positioning properties.
.wrapper {
background-color: yellowgreen;
display: block;
padding: 10px;
max-width: 180px;
position: relative; /* new; set bounding box for flex container */
min-height: 40px; /* new */
}
.parent {
display: flex;
flex-flow: row nowrap;
background-color: yellow;
position: absolute; /* new; remove flex container from document flow */
}
.child {
/* display: block; <-- not necessary */
background-color: orange;
margin: 10px;
min-width: 50px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
</div>
</div>

Related

CSS Display: inline-block but Stack Divs only if they overlap

I have the following divs below:
.parent {
padding: 10px;
background: grey;
}
.child {
background: green;
display: block;
position: relative;
width: 50px;
}
.stacked {
left: 0px;
}
.three {
left: 200px;
}
<div class="parent">
<div class="child stacked">div1</div>
<div class="child stacked">div2</div>
<div class="child three">div3</div>
</div>
This looks like the following:
I would like divs 1 and 2 to stack as they do, but since div3 does not collide with the divs above, I'd like it to vertically aline with div 1.
If I switch display to inline or inline-block, it pushes div 2 to the right of div one. and the left values are not accurate to the parant.
The left values of the divs will be dynamically generated so I cannot know if the divs are overlapping or not.
Is this possible?
Edit: If you really want to align the 3rd div using positioning, then you can do it like so:
.parent {
padding: 10px;
background: grey;
position: relative;
}
.child {
background: green;
display: block;
position: relative;
width: 50px;
}
.stacked {
position: relative;
left: 0px;
}
.three {
position: absolute;
left: 200px;
top: 10px;
}
<div class="parent">
<div class="child stacked">div1</div>
<div class="child stacked">div2</div>
<div class="child three">div3</div>
</div>
You can use the column-count property like so:
.parent {
padding: 10px;
background: grey;
column-count: 2;
}
.child {
background: green;
display: block;
width: 50px;
}
<div class="parent">
<div class="child">div1</div>
<div class="child">div2</div>
<div class="child">div3</div>
</div>
Or you can use flexbox to wrap vertically, like so:
.parent {
padding: 10px;
background: grey;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 50px;
}
.child {
background: green;
display: block;
width: 50px;
}
<div class="parent">
<div class="child">div1</div>
<div class="child">div2</div>
<div class="child">div3</div>
</div>
Here's using grid:
.parent {
padding: 10px;
background: grey;
display: grid;
grid-auto-flow: column;
grid-template-rows: 1fr 1fr;
}
.child {
background: green;
display: block;
width: 50px;
}
<div class="parent">
<div class="child">div1</div>
<div class="child">div2</div>
<div class="child">div3</div>
</div>
Try this :
wrap div3 item in another div and give it a class property of flex-container.
.flex-container {
align-content: flex-start;
}
Ensure the flex direction is horizontal.

Overflow auto not working with justify-content: flex-end

I'm trying to get an element to have items aligned to the right, and all overflowing elements to be hidden but accessed by scrollbar.
But it seems like the scrollbar disappears when specifying justify-content: flex-end. Why is that, and how do I fix it?
Here is demo: https://jsfiddle.net/efguz4mp/1/
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
justify-content: flex-end;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
...and here is demo without justify-content: flex-end;: https://jsfiddle.net/efguz4mp
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
When an overflow occur to the left (or top), a scroll doesn't get rendered, and the reason is that a HTML document's normal flow is left-to-right (top-to-bottom).
Flexbox has a row-reverse direction, which will solve that, thought 2 things comes with that:
One need to reorder the items or use an inner wrapper
I.a. Firefox and Edge doesn't show the scroll (possible bug)
Stack snippet
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
flex-direction: row-reverse;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
/* no wrapper */
.row > .box:nth-child(1) { order: 6; }
.row > .box:nth-child(2) { order: 5; }
.row > .box:nth-child(3) { order: 4; }
.row > .box:nth-child(4) { order: 3; }
.row > .box:nth-child(5) { order: 2; }
.row > .box:nth-child(6) { order: 1; }
/* wrapper */
.inner {
display: flex;
}
<div class="row">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
<div><br><br></div>
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Possible workarounds are:
Use direction: rtl to change the flow direction
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
direction: rtl;
}
.inner {
display: flex;
direction: ltr;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Use transform to flip the row element
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
transform: scale(-1,1); /* flip horizontally */
}
.inner {
display: flex;
transform: scale(-1,1); /* reset so items is not backwards */
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Use a script on page load to scroll to the right
window.addEventListener("load", function(e) {
var el = document.querySelector(".row");
el.scrollLeft = el.scrollWidth;
});
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
The main problem is that you're dealing with a contradiction:
The justify-content property is designed to distribute extra space in the container.
However, an overflow condition occurs when there is no space left in the container.
Basically, justify-content and overflow have no association. The former applies only inside the container. The latter applies only outside the container.
With justify-content: flex-end, the flex items must be packed at the end of the container (not the end of the flex-start overflow area).
If the end-aligned items are too big to fit in the container, they will overflow on the start side, which is what you're seeing in your layout. But because the overflow property only applies in the direction of the writing mode (LTR, in this case), scrollbars are not rendered (more details).
So I would suggest forgetting about justify-content to make this layout work.
Instead, consider this: Use an invisible spacer item to push your content items to the right.
.row {
display: flex;
overflow: auto;
max-width: 500px;
background: #DADADA;
}
.box {
flex: 0 0 200px;
height: 40px;
margin: 4px 10px;
background: red;
}
.row::before {
content: "";
flex: 0 0 400px;
visibility: hidden;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
You'll notice that the last item margin collapses. That issue is explained here:
Last margin / padding collapsing in flexbox
Here's how I would recommend you do it
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
flex: 1;
display: flex;
overflow: auto;
}
.box {
display: flex;
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>

Flex - make parent width of children?

I have a flex box layout. I want the width of .outer-2 to be the width of its children, with .outer-1 and outer-3 taking up the rest of the space.
How can I achieve this?
JSFiddle
.container {
display: flex;
}
.outer-1 {
background: red;
height: 100px;
flex: 1;
}
.outer-2 {
display: flex;
flex: 1;
}
.outer-3 {
background: blue;
height: 100px;
flex: 1;
}
.inner {
flex-basis: 30px;
background: green;
height: 100px;
margin: 0 3px;
}
<div class="container">
<div class="outer-1">
</div>
<div class="outer-2">
<div class="inner">
</div>
<div class="inner">
</div>
<div class="inner">
</div>
</div>
<div class="outer-3">
</div>
</div>
You need to change the flex properties for the second child of container preventing it from growing to fit it's parent. That, and adding a width or min-width to each .inner element will prevent their parent from collapsing them down.
.container{
display: flex;
}
.outer-1{
background: red;
height: 100px;
flex: 1;
}
.outer-2{
display: flex;
flex: 1;
}
.outer-3{
background: blue;
height: 100px;
flex: 1;
}
.inner{
width: 30px;
flex: 1 0 30px;
background: green;
height: 100px;
margin: 0 3px;
}
<div class="container">
<div class="outer-1">
</div>
<div class="outer-2">
<div class="inner">
</div>
<div class="inner">
</div>
<div class="inner">
</div>
</div>
<div class="outer-3">
</div>
</div>

How to word-break text in a flex display when the text is long?

I need to make a responsive web, so that the width of parent is dynamic.
There are two flex items, one is long (dynamic) and another one is short (static).
I hope the result can look like the second line, that the long text is broken (or hidden when overlap), and the short text is always displayed correctly.
I tried to use flex-shrink: 0 but seems there is always an overflow.
How can I get rid of the overflow in this case?
I do need flex layout, and the js should not be involved.
.parent {
display: flex;
flex-direction: row;
width: 15rem;
background: yellowgreen;
padding: 10px;
overflow: hidden;
}
.flex-item {
width: 10em;
padding: 10px;
background: yellow;
flex: 1 1 50%;
}
.block1 {
background: red;
}
.block2 {
background: orange;
}
.nos {
flex-shrink: 0 !important;
}
<div class="parent">
<div class="flex-item">
<div class="block1">
longlonglonglonglonglonglonglonglonglonglonglonglonglong
</div>
</div>
<div class="flex-item nos">
<div class="block2">
Display
</div>
</div>
</div>
<br/>
<div class="parent">
<div class="flex-item">
<div class="block1">
longlonglonglonglong...
</div>
</div>
<div class="flex-item">
<div class="block2">
Display
</div>
</div>
</div>
https://jsfiddle.net/templefox/Lw3hhz8j/
just put word-break:break-all property to its parent div. You can see it live by clicking this JSFiddle link
.parent {
display: flex;
width: 15rem;
padding: 10px;
background: yellowgreen;
/* overflow: hidden <-- not necessary at this point */
/* flex-direction: row <-- default value; can be omitted */
}
.flex-item {
/* width: 10em <-- not necessary at this point */
/* flex: 1 1 50% <-- not necessary at this point */
padding: 10px;
background: yellow;
display: flex; /* new */
min-width: 0; /* see note #1 */
}
.block1 {
width: 10em;
overflow: hidden; /* see note #2 */
text-overflow: ellipsis; /* see note #2 */
white-space: nowrap; /* see note #2 */
background: red;
}
.block2 {
background: orange;
}
/* .nos { flex-shrink: 0 !important; } */
<div class="parent">
<div class="flex-item">
<div class="block1">longlonglonglonglonglonglonglonglonglonglonglonglonglong</div>
</div>
<div class="flex-item">
<div class="block2">Display</div>
</div>
</div>
<br/>
<div class="parent">
<div class="flex-item">
<div class="block1">longlonglonglonglong...</div>
</div>
<div class="flex-item">
<div class="block2">Display</div>
</div>
</div>
revised fiddle
Notes:
Why doesn't flex item shrink past content size?
Applying an ellipsis to multiline text
Something like this.
*{
box-sizing:border-box;
}
.parent {
display: flex;
flex-direction: row;
width: 16rem;
background: yellowgreen;
padding: 10px;
overflow: hidden;
position: relative;
}
.flex-item {
width: 100%;
padding: 10px;
background: yellow;
flex: 1 1;
}
.block1 {
background: red;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right:70px;
}
.block2 {
background: orange;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nos {
flex-shrink: 0 !important;
position: absolute;
right: 10px;
max-width: 70px;
}
<div class="parent">
<div class="flex-item">
<div class="block1">
longlonglonglonglonglonglonglonglonglonglonglonglonglong
</div>
</div>
<div class="flex-item nos">
<div class="block2">
Display
</div>
</div>
</div>

set div equally in the parent div along with text

I want divs to be set equally in the parent div along with text.
Just shown in the image.
#container {
text-align: justify;
}
#container > div {
width: 90px; /* Declare your value. Can be in relative units. */
display: inline-block;
vertical-align: top;
background: #f2f1f1;
/* IE fix. */
*display: inline;
zoom: 1;
height: 90px;
}
#container:after {
content: "";
width: 100%;
display: inline-block;
}
<div id="container">
<div></div>
<div></div>
<div></div>
</div>
Thank You.
Like this?
#container {
display: flex;
justify-content: space-between;
width: 400px;
margin: 0 auto;
}
#container .box-container {
width: 90px; /* Declare your value. Can be in relative units. */
display: flex;
flex-direction: column;
align-items: center;
}
#container .box-container .img {
width: 90px;
height: 90px;
background: #e7e7e7;
}
<div id="container">
<div class="box-container">
<div class="img"></div>
<p>text</p>
</div>
<div class="box-container">
<div class="img"></div>
<p>text</p>
</div>
<div class="box-container">
<div class="img"></div>
<p>text</p>
</div>
</div>