Fit flex parent cross-axis to items - css

Where the parent has display: flex; flex-direction: column, is it possible to make the parent's width expand to fit a flex item wider than the parent?
It's worth noting that the grandparent does not have display: flex nor a fixed width. It has a min-width: 100% though.

Yes, you can, and by using inline-flex instead of flex, it will grow with the child.
The reason why the flex parent won't grow along with its child when using flex is because flex work similar to a block element, and block element won't grow larger than its parent, which inline element does.
This can be seen here, where the grand parent, with or w/o min-width: 100%, won't grow with its content, but the inline-flex will. This would also be the case if the flex element would instead have inline-block.
Still, the parent's content will overflow and effect its surroundings as if it would grow with content, and make the outer scroll to show up.
Why the parent with min-width is slightly wider is because of the padding not being included in its set width, so adding box-sizing: border-box; to its rule will make them equal wide.
Stack snippet
.parent {
padding: 20px;
background: yellow;
}
.parent.with-min-width {
min-width: 100%;
}
.flex {
display: inline-flex;
flex-direction: column;
background-color: red;
padding: 20px;
}
.flex .item {
width: 800px;
padding: 20px;
background-color: blue;
}
<div class="parent">
<div class="flex">
<div class="item">
</div>
</div>
</div>
<div class="parent with-min-width">
<div class="flex">
<div class="item">
</div>
</div>
</div>

Using inline-flex on the parent instead of flex and inline-block on the grandparent should do the trick.
Example B shows the modifications. If the img is wider than the viewport the parent and the grandparent will accommodate it (shrink your window down so img is wider than the viewport then scroll right).
html,body {
width: auto;
}
.grandparent {
width: 300px;
background-color: blue;
padding: 10px;
}
.parent {
display: inline-flex;
flex-direction: column;
background-color: red;
padding: 10px;
}
.exampleB .grandparent {
min-width: 100%;
width: auto;
display: inline-block;
}
.exampleB .parent {
width: auto;
}
<section class="exampleA">
<div class="grandparent">
<div class="parent">
<div class="child">
<img src="//placehold.it/500x100"/>
</div>
</div>
</div>
</section>
<br/>
<section class="exampleB">
<div class="grandparent">
<div class="parent">
<div class="child">
<img src="//placehold.it/500x100"/>
</div>
</div>
</div>
</section>

Related

CSS: responsive grid/flex layout when there are intermediate divs between the parent and children? [duplicate]

I have a simple flex element with some children, something like this:
.container{
display: flex;
flex-wrap: wrap;
}
.container div.flex-box{
width: 200px;
margin: 20px;
padding: 20px;
font-size: 40px;
border: 1px solid;
}
<div class='container'>
<div class='flex-box'>one</div>
<div class='flex-box'>two</div>
<div class='flex-box'>three</div>
<div class='flex-box'>four</div>
<div class='flex-box'>five</div>
<div class='flex-box'>six</div>
</div>
I am using flex wrap so, when screen goes smaller they stack.
Now, I want to reload fourth and fifth element using an ajax call to reload both elements, for this I need to put both children inside a container, but when I do, it becomes a new flex child
.container{
display: flex;
flex-wrap: wrap;
}
.container div.flex-box{
width: 200px;
margin: 20px;
padding: 20px;
font-size: 40px;
border: 1px solid;
}
<div class='container'>
<div class='flex-box'>one</div>
<div class='flex-box'>two</div>
<div class='flex-box'>three</div>
<div class='subcontainer'>
<div class='flex-box'>four</div>
<div class='flex-box'>five</div>
</div>
<div class='flex-box'>six</div>
</div>
I am looking for a way to ingore this "subcontainer", and keep the children working as before.
Is this possible?
Use display:contents (https://css-tricks.com/get-ready-for-display-contents/) but pay attention to the support (https://caniuse.com/#feat=css-display-contents)
.container {
display: flex;
flex-wrap: wrap;
}
.container div.flex-box {
width: 200px;
margin: 20px;
padding: 20px;
font-size: 40px;
border: 1px solid;
}
.subcontainer {
display: contents
}
<div class='container'>
<div class='flex-box'>one</div>
<div class='flex-box'>two</div>
<div class='flex-box'>three</div>
<div class='subcontainer'>
<div class='flex-box'>four</div>
<div class='flex-box'>five</div>
</div>
<div class='flex-box'>six</div>
</div>
If the element is a child of a flex container, then it becomes a flex item. That's the general rule.
However, most browsers will ignore that rule when the child is absolutely positioned.
I'm not sure that's a useful solution in this case, but that's what you would have to do: absolutely position .subcontainer and make it flex container, so that the children become flex items.

IE11 flex:1 causes content to overflow when parent has no fixed height

I have an element which depending on the scenario can have a fixed height or a height of auto / undefined.
I need a title at the top, and a footer at the bottom, with a content area in between which should fill the available space. Using flexbox and flex:1 works fine if the parent element has a fixed height, but in IE11 if no height is specified, the content in the element with flex:1 will overflow.
See example here:
https://plnkr.co/edit/JymmiJUwrPxiM2qS?open=lib%2Fscript.js&preview
In the "Fluid height" demo, the content overflows onto the footer text. The content element (.body) occupies no space at all. I expect the content to dictate the height of the .body element.
I could have an extra class that turns off flex:1 if there is no fixed height specified, but I won't know this ahead of time, or have control over weather a height is specified or not. Also I'm not looking to use any other sticky footer solutions (table layout, absolute positioning, etc)
Code from plnkr:
<div class="container" style="height: 150px; margin-bottom: 50px;">
<div class="title">Fixed height</div>
<div class="body">
Content
</div>
<div class="footer">Footer</div>
</div>
<div class="container">
<div class="title">Fluid height</div>
<div class="body">
Content
</div>
<div class="footer">Footer</div>
</div>
.container {
border: 1px solid #000;
display: -ms-flexbox;
display: flex;
-ms-flex-direction: column;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
}
.title {
border-bottom: 1px solid #ccc;
}
.body {
-ms-flex: 1;
flex: 1;
/* overflow: auto; */
}
.footer {
opacity: 0.5;
}
For IE11 you need to reset flex-shrink to 0 for .body, Also, prefix are not needed (i run a genuine IE11 to let you know):
https://jsbin.com/takanicuyi/1/edit?html,css,js,output //works with IE11
.container {
border: 1px solid #000;
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 10px;
}
.title {
border-bottom: 1px solid #ccc;
}
.body {
flex: 1 0 auto;
}
.footer {
opacity: 0.5;
}
<div class="container" style="height: 150px; margin-bottom: 50px;">
<div class="title">Fixed height</div>
<div class="body">
Content
</div>
<div class="footer">Footer</div>
</div>
<div class="container">
<div class="title">Fluid height</div>
<div class="body">
Content
</div>
<div class="footer">Footer</div>
</div>
Similar issue with img : Flexbox on IE11: image stretched for no reason?

Flex box items width basing off of parent container width

I have a parent container that has a max width and I want there to be 3 boxes to a line. I am using flex for this but I want the boxes to take up the full width of the parent container which I am only able to achieve by hard-coding the width of the boxes. How can I have them adapt to the width of the sections container rather than me putting a 32% width on the boxes?
HTML
<div class="account-component>
<div class="cart-products-container">
<div class="sections">
<div class="cart-product">
</div>
<div class="cart-product">
</div>
<div class="cart-product">
</div>
<div class="cart-product">
</div>
<div class="cart-product">
</div>
<div class="cart-product">
</div>
</div>
</div>
</div>
CSS
.account-component {
max-width: 1240px;
text-align: center;
margin: 0 auto;
display: flex;
margin-top: 100px;
.sections {
display: flex;
flex-wrap: wrap;
.cart-product {
width: 32%;
margin-bottom: 25px;
height: 445px;
background-color: pink;
&:nth-child(3n+2) {
margin-right: 24px;
margin-left: 24px;
}
}
}
}
To get the desired effect, you just need to change:
.cart-product {
flex: 0 0 33%;
margin-bottom: 25px;
height: 445px;
background-color: pink;
}
You can not use percentage on child element if you did not set the width (not max-with) of the parent element, because you won't have a width to depend on.
In your case, use flex to set the percentage of the child elements.
Here's a sample fiddle: https://jsfiddle.net/gadawag/0by7dm81/6/

Absolute scrollable div inside flex container without fixed height, is it possible?

How do I set a div as scrollable (absolute) without fixed height filling entire view, while inside a flex-box?
(https://imgur.com/7v5OFas)
(typo at the right section, its fixed width, the only height expected is to be fullpage everything)
https://codepen.io/anon/pen/oJyOOp?editors=1000
(if I add height to the relative parent of the red section, it works, but I cant have a fixed height. Adding 100% from html to the relative parent also works, but I can't also do that.)
currently it goes:
<div style="display:flex">
<div style="flex-grow:1">
<div style="display:flex">
<div style="width:45px...">
....
</div>
<div ...header code>
....
</div>
<div style="flex-grow:1; top:70px; position: relative">
<div style="position: absolute; top:0; left:0; right:0; bottom: 0; overflow: auto>
</div>
</div>
</div>
</div>
<div style="width:45px...">
....
</div>
</div>
It ends up filling the header height.
I would drop the idea of absolute content if its not necesarry and try something similiar to:
html, body {
min-height: 100%;
height: 100%;
margin: 0;
}
.container{
background: blue;
display: flex;
height: 100%;
flex-flow: row;
}
.sidebar{
background: red;
height: 100%;
width: 200px;
}
.contentWrapper{
display: flex;
flex-flow: column;
flex: 1;
}
.header {
background: yellow;
height: 100px;
width: 100%;
}
.content {
flex: 1;
overflow: auto;
}
.scrollableContent {
height: 3000px;
}
<div class="container">
<div class="sidebar"></div>
<div class="contentWrapper">
<div class="header"></div>
<div class="content">
<div class="scrollableContent">
</div>
</div>
</div>
</div>
Where you basically make every container a flex and the non scalable part of its content will have fix width/height and the other part get flex: 1 which is shorthand for taking rest of the space.

Auto-resize image in flex item

I have the following html :
<div class="main-container">
<h1>A title</h1>
<p>Some text</p>
<div class="sub-container">
<img src="">
</div>
</div>
With the following CSS :
.main-container{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.sub-container{
flex-grow:2;
background-color: green;
}
Please note that I don't know the size of the container above "main-container". I'm using flex because I want the div in "main-container" to occupy all the remaining space at the bottom.
What I want is to have an image in "sub-container" which fits its parent's size in both directions (height and width). Right now if I add an image into "sub-container" it overflows and doesn't get scaled at all.
I know that flex only works for immediate children (i.e. "sub-container" but not the image inside). I tried to use flex on "sub-container" too, but I couldn't achieve anything satisfactory.
Is this layout you wanted?
Using flex: 1 1 0 to control the sub-container and using width: 100% could make the image to fit the container.
.main-container{
border: 3px solid green;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.sub-container{
flex-grow: 1 1 0;
background-color: green;
display: flex;
}
.sub-container img {
width: 100%;
height: 100%;
}
<div class="main-container">
<h1>A title</h1>
<p>Some text</p>
<div class="sub-container">
<img src="https://picsum.photos/1080/600">
</div>
</div>
You can use this class:
.img-fluid {
max-height:100%;
height:auto;
}
Don't forget to add .img-fluid to your img

Resources