Flex - make parent width of children? - html

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>

Related

Is it possible to make a child of a flex column be 100% width of its flex container?

I'm trying to make the red box be the same width as the flex container outlined in black.
.container {
display: flex;
width: 80%;
margin: auto;
column-gap: 1em;
outline: 1px solid black;
}
.a {
background: #f002;
flex: 3;
}
.b {
background: #00f2;
flex: 2;
}
.box {
background: #f0f2;
margin: 1em 0;
padding: 1em;
}
.fw {
background: red;
}
<div class="container">
<div class="a">
<div class="box">
A
</div>
<div class="box fw">
B
</div>
<div class="box">
C
</div>
</div>
<div class="b">
<p>Some text here</p>
</div>
</div>
This is how you can do it in this case that you have presented. The code might need to be changed if the propertion between the first column and second column change.
.container {
display: flex;
width: 80%;
margin: auto;
column-gap: 1em;
outline: 1px solid black;
}
.a {
overflow: visible;
background: #f002;
flex: 3;
}
.b {
background: #00f2;
flex: 2;
}
.box {
background: #f0f2;
margin: 1em 0;
padding: 1em;
}
.fw {
width: calc(166.666666% - 1em);
background: red;
}
<div class="container">
<div class="a">
<div class="box">
A
</div>
<div class="box fw">
B
</div>
<div class="box">
C
</div>
</div>
<div class="b">
<p>Some text here</p>
</div>
</div>

Visible overflow on X axis, but auto/scroll on axis Y

To keep things neat and short:
https://jsfiddle.net/m53ockLu/
.container {
max-height: 500px;
background: grey;
}
.sidebar {
height: 100vh;
width: 150px;
overflow-x: scroll;
overflow-y: auto;
background: red;
}
.element {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 5px;
height: 200px;
width: 20px;
background: green;
}
.first {
position: relative;
display: block;
height: 20px;
width: 100px;
background: pink;
}
.second {
display: inline-block;
}
.second-absolute {
position: absolute;
height: 20px;
width: 250px;
background: purple;
}
<div class="container">
<div class="sidebar">
<div class="element">
<div class="first"></div>
<div class="second">
<div class="second-absolute"></div>
</div>
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
Is it possible to keep the red container scrollable on vertical axis, and at the same time make the purple (.second-absolute) element overflow this red container horizontally? I'm totally out of ideas, I thought that overflow-x & overflow-y should do the trick, but no dice.
Thank you very much for any help.
Is it possible to keep the red container scrollable on vertical axis, and at the same time make the purple (.second-absolute) element overflow this red container horizontally?
No.
I tried Ethan's suggestion and couldn't get the purple box to visibly overflow the scrollbar:
.container {
max-height: 500px;
background: grey;
}
.sidebar {
height: 100vh;
width: 150px;
overflow-y: scroll;
background: red;
}
.element {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 5px;
height: 200px;
width: 20px;
background: green;
}
.first {
position: relative;
display: block;
height: 20px;
width: 100px;
background: pink;
}
.second {
display: inline-block;
}
.second-absolute {
position: absolute;
height: 20px;
width: 250px;
background: purple;
}
<div class="container">
<div class="sidebar">
<div class="element">
<div class="first"></div>
<div class="second">
<div class="second-absolute"></div>
</div>
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
I don't think the browser will let you overflow the scrollbar, I even put z-index, explicitly said to visibly overflow, played around with the position property etc.
Consider this example of letting the content dictate the size:
.container {
max-height: 500px;
background: grey;
}
.sidebar {
height: 100vh;
width: max-content;
overflow-y: auto;
background: red;
}
.element {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 5px;
height: 200px;
background: green;
}
.first {
display: block;
height: 20px;
background: pink;
}
.second {
display: inline-block;
}
.second-absolute {
height: 20px;
width: 250px;
background: purple;
}
<div class="container">
<div class="sidebar">
<div class="element">
<div class="first"></div>
<div class="second">
<div class="second-absolute"></div>
</div>
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
</div>
You made the parent div sidebar have overflow-x: scroll;, overflow-y: auto;. Instead, make each child have its own overflow properties instead of the parent.

Create a circle that fills up the remaining space in a flexbox cell

I have a 2-cell flexbox with a fixed-height (mobile screen), and one cell stacked on top of the other. I need all of the content of the top-cell to be displayed.. the bottom-cell should yield as much space as possible to allow this. This part was easy.
.main-container {
height: 400px;
width: 200px;
display: flex;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background-color: lightgrey;
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space"></div>
</div>
... with that the content-container will grow as needed (in this example it's 100px) and the rest is taken up by the remaining-space cell.
What I need to do is fill the remaining-space cell with a circle that is as big as it can be, but doesn't force the remaining-space cell to grow in height/width... and I need to do it with just html/css.
The only way I've seen to enforce a 1:1 ratio (square/circle) is by using the padding-bottom trick where the padding is calculated using the element's width. This doesn't work for me because remaining-space cell might have a larger width than it's height.. which will cause the cell to grow in height. This is especially difficult in that the container is responsive so the actual width in pixels is never known.
A simple gradient can do it:
.main-container {
height: 400px;
width: 200px;
display: inline-flex;
vertical-align: top;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background:
radial-gradient(circle closest-side, red 98%, transparent)
lightgrey;
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space"></div>
</div>
<div class="main-container" style="height:200px;">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space"></div>
</div>
Clip-path can also do it:
.main-container {
height: 400px;
width: 200px;
display: inline-flex;
vertical-align: top;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background: lightgrey;
}
.remaining-space>div {
height: 100%;
background: red;
clip-path: circle(closest-side)
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div></div>
</div>
</div>
<div class="main-container" style="height:200px;">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div></div>
</div>
</div>
Where you can also have content inside
.main-container {
height: 400px;
width: 200px;
display: inline-flex;
vertical-align: top;
flex-direction: column;
}
.content-container {
flex-grow: 1;
flex-shrink: 0;
background-color: green;
}
.content {
height: 100px;
}
.remaining-space {
flex-grow: 0;
flex-shrink: 1;
height: 100%;
background: lightgrey;
}
.remaining-space>div {
height: 100%;
background: red;
clip-path: circle(closest-side);
display:flex;
align-items:center;
justify-content:center;
font-size:30px;
}
<div class="main-container">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div> text </div>
</div>
</div>
<div class="main-container" style="height:200px;">
<div class="content-container">
<div class="content"></div>
</div>
<div class="remaining-space">
<div> text </div>
</div>
</div>

Why doesn't flex direction column with align-items=center center image properly

I stumbled upon an issue with image centering within a flexbox with direction:column.
Imagine you have two elements within a flexbox, where the first one contains an image:
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
.image-container {
flex: 1;
align-self: center;
.img {
height: 100%;
}
}
.another-flex-child {
flex: none;
background-color: red;
}
}
I would expect the image to be center horizontally within the div, but it appears the left border of the image is exactly at the center of the div.
When I replace the image with another div which contains some text it is placed as expected.
Can anybody explain to me whats happening there?
Checkout this fiddle
Because your <div> that contains the image (and has align-self: center on it) is by default a block-level element, and has a width of 100% by default. As such, it is constrained in relation to the parent.
In order to have your image centered correctly, you'll want to add display: contents with:
container .image-container {
display: inline;
}
This can be seen in the following:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.container .image-container {
flex: 1;
align-self: center;
display: contents;
}
.container .image-container .img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
The issue is that you are using an SVG with no intrinsic dimension and only an intrinsic ratio so it's like your image has a width equal to 0 which make its centred container with a width equal to 0, too.
Here is before using height:100%
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
}
.img {
/*height: 100%;*/
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
After setting height:100% the image will fill all the space and will keep its ratio but you will have an overflow because the browser will not go back to calculate the width of the container again:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg" >
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
To avoid this give the image a width and make sure to add min-height:0 to the container to allow it to shrink
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
min-height:0;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg" width="250">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
If you were initially using an image with intrinsic dimension you won't have this issue and you don't need to define a width. You will only need to add min-height:0 to avoid the overflow:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
min-height:0;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://picsum.photos/id/1/400/400">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
Note that the above doesn't work the same way in Firefox and you will need to add text-aling:center to make sure it works the same everywhere:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
text-align:center;
min-height:0;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://picsum.photos/id/1/400/400">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
You will notice that the difference is related to the width calculation of the container which a bit complex due to the use of height:100%
Things may get worse if the size of the image is very small:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
text-align:center;
min-height:0;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://picsum.photos/id/1/50/50">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
In Firefox text-align:center will do nothing and you may need a nested flexbox container
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
justify-content:center;
border:2px solid blue;
display:flex;
min-height:0;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://picsum.photos/id/1/50/50">
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
The below is almost the same issue you were having with the initial SVG that can fixed with this same code but it won't remove the overflow:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
display:flex;
justify-content:center;
border:2px solid blue;
}
.img {
height: 100%;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg" >
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
Another intresting thing to note is that your initial code may work fine if you add height:100% to the container making the calculation of the nested height easier:
.container {
height: 300px;
background-color: green;
display: flex;
flex-direction: column;
}
.image-container {
flex: 1;
align-self: center;
border:2px solid blue;
box-sizing:border-box;
height:100%;
}
.img {
height: 100%;
display:block;
}
.another-flex-child {
flex: none;
background-color: red;
}
.spacer {
height: 20px;
}
<div class="container">
<div class="image-container">
<img class="img" src="https://interactive-examples.mdn.mozilla.net/media/examples/firefox-logo.svg" >
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
<div class="spacer"></div>
<div class="container">
<div class="image-container">
<div>Properly centered content</div>
</div>
<div class="another-flex-child">
Random content here
</div>
</div>
Add the justify-content like below:
.image-container {
flex: 1;
align-self: center;
justify-content:center;
}
it should works

Flexbox nested container not expanding to fill parent in safari

I am trying to make a nested 100% screen layout but I am running into a problem where the nested container does not fill 100% of the space of the parent cell in safari, even tho the cell itself does expand to fill all the available space. If I make the subContainer the actual flex cell as well it works, but I canĀ“t do that for practical reasons. Any ideas?
jsfiddle
HTML:
<div id="masterContainer">
<div id="header">
header
</div>
<div id="content">
<div id="subContainer">
<div id="left">
left
</div>
<div id="right">
right
</div>
</div>
</div>
</div>
CSS:
#masterContainer {
display: flex;
flex-direction: column;
width: 200px;
height: 200px;
}
#header {
background: yellow;
}
#content {
background: grey;
flex: 1;
}
#subContainer {
display: flex;
width: 100%;
height: 100%;
}
#left {
background: red;
width: 50;
}
#right {
background: green;
flex: 1;
}
This is a workaround for this problem in Safari.
Since Safari seems to avoid calculation for non-flex nested containers.
Take a look to this answer
#masterContainer {
display: flex;
flex-direction: column;
width: 200px;
height: 200px;
}
#header {
background: yellow;
}
#content {
background: grey;
flex: 1;
position: relative;
}
#subContainer {
display: flex;
width: 100%;
height: 100%;
position: absolute;
}
#left {
background: red;
width: 50px;
}
#right {
background: green;
flex: 1;
}
<div id="masterContainer">
<div id="header">
header
</div>
<div id="content">
<div id="subContainer">
<div id="left">
left
</div>
<div id="right">
right
</div>
</div>
</div>
</div>