Why does a flex container shrink when applying display: flex to body? - css

I'm making an observation more so than stating a problem, if only to help anyone who's also noticed. I'm following a tutorial on flexbox when I accidently comment out display: flex on body{}. The container expands from 120px (flex-direction: column) wide to 100% of the viewport, horizontally. Display: grid also expands to 100% of the horizontal viewport. This observation is enough for me to post the question because I struggle working with flexbox and I end up applying padding and margin manually. I wonder if anyone else has any observations that are not explicitly stated in flexbox documentation.
<div class="flex-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
</div>
.flex-container {
display: flex;
flex-direction: column;
align-items: center;
}
.item {
background-color: blue;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100px;
width: 100px;
margin: 10px;
}
Why does display: flex shrink the container?

When an element has display: flex applied—making it a flex container—certain default settings come into play. Two of these settings are flex-direction: row on the container and flex-basis: auto on the items.
With display: flex on the body element, the flex item (.flex-container) is automatically set to flex-basis: auto, which is the width of the content. That's why the nested container "shrinks".
When display: flex is removed, the body element reverts back to display: block. Its child (.flex-container) is no longer a flex item and takes the default width: 100% of block elements.
If you want a flex item to expand to 100% width, just give it flex-grow: 1 or flex: 1.
body {
display: flex;
}
.flex-container {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid red;
}
.item {
background-color: blue;
color: white;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100px;
width: 100px;
margin: 10px;
}
<div class="flex-container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="item">item 3</div>
</div>

Related

Equal width flex columns when the container has fluid width

Consider the following HTML code:
<div class="ungrouped-ordered-item">
<div class="information-container">
<div class="originating-order-id"> #00019405 </div>
<div class="placed-by"> Placed by: 18175 </div>
</div>
<div class="indicator-container">
<div class="indicator"> Unpaid </div>
<div class="indicator" >Pending </div>
</div>
</div>
with the following css:
.ungrouped-ordered-item {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.information-container {
display: flex;
flex-direction: column;
}
.indicator-container {
display: flex;
flex-direction: row;
align-items: center;
}
.indicator-container .indicator {
display: flex;
justify-content: space-between;
align-items: center;
flex: 1;
padding: 0 10px;
border: 1px solid #2e2240;
}
The design I am aiming for, is:
to let the outermost flex containers (.ungrouped-ordered-item) children, grow as they need, and leave space between them, so that they are aligned to the left and right respectively of their containers
to make the children of the inner flex container (.indicator-container .indicator) be equal-width, by taking up the width of the wider element (in this case, it being the element with the text "Pending")
My first goal is achieved, but it seems, that even if adding flex: 1 to the .indicator containers, the browser will not correctly calculate the width of the two elements, and they will have uneven widths. I am presuming that this is because that their container, .indicator-container, has a fluid width. Am I right in this? How can I achieve my desired effect with all fluid width containers? (preferably without javascript).
Here's a fiddle also!
What is the argument against a width:50% for the .indicatorbox?
.ungrouped-ordered-item {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.information-container {
display: flex;
flex-direction: column;
}
.indicator-container {
display: flex;
flex-direction: row;
align-items: center;
gap: 10px;
}
.indicator-container > * {
border: 1px solid #2e2240;
padding: 0 10px;
flex-wrap: wrap;
}
.indicator-container .indicator {
width: 50%;
text-align: center;
}
<div class="ungrouped-ordered-item">
<div class="information-container">
<div class="originating-order-id"> #00019405 </div>
<div class="placed-by"> Placed by: 18175 </div>
</div>
<div class="indicator-container">
<div class="indicator"> Unpaid </div>
<div class="indicator" >Pending long long</div>
</div>
</div>
Changing the .indicator-container class from flex to grid and using automatic columns solves my problem. Although, it doesn't have as much coverage as flex, for my needs, this works:
.indicator-container {
display: grid;
grid-auto-columns: minmax(0, 1fr);
grid-auto-flow: column;
}
Here's the updated fiddle also.

Flex child shrinks when applying "align-self: center"

I'd like to horizontally center align a flex child inside a flex container.
However, when the child gets align-self: center it shrinks to width = 0.
Note that both the container and the child have max-width.
How would you solve this?
.container {
display: flex;
flex-direction: column;
max-width: 400px;
outline: 2px solid red;
}
.child {
display: flex;
flex-direction: column;
max-width: 200px;
height: 50px;
background-color: #ccc;
/* This causing the child to shrink to width = 0 */
/* align-self: center; */
}
<div class="container">
<div class="child">
</div>
</div>
The issue is the stretch effect that you disable by changing the alignment of the element. By default align-items is set to stretch thus the element will try to fill its parent width (or height for a row direction).
You can put back this feature using width:100%
.container {
display: flex;
flex-direction: column;
max-width: 400px;
outline: 2px solid red;
}
.child {
display: flex;
flex-direction: column;
max-width: 200px;
height: 50px;
width:100%;
background-color: #ccc;
align-self: center;
}
<div class="container">
<div class="child">
</div>
</div>
align-items sets the default alignment for all of the flex container’s items, including anonymous flex items. align-self allows this default alignment to be overridden for individual flex items.ref

Center align a div underneath a row of divs using flexbox

This is how it looks now.
I want the välj div to be centered below the other ones.
I am using flexbox.
What I have done now is to wrap all the divs in a container, and then add:
display: flex;
align-items: center;
justify-content: center;
to the container
the row of divs also have a container around it. With the value:
display: flex;
flex-flow: row;
justify-content: center;
align-content: center;
align-items: center;
The last "button" div (välj), has the value align-self: center;.
Am I missing something, or should now it be centered by now?
The align-* properties in Flexbox (align-items/content/self) defines how the browser distributes space between and around flex items along the cross-axis of their container.
So in your case, where the container has row direction, the align-self: center will center the button vertically, though if its parent doesn't have a height higher than the flex item, one won't visually see it.
Based on you say there is one row div around the price items and one around the button, you have two main options to center the button:
Change the container to column direction and the align-self: center will center the button horizontally.
Replace align-self: center with margin: auto
The below works with a flexbox for the row only.
.item {
width: 20%;
height: 50px;
background: blue;
border: thin solid red;
}
.row {
display: flex;
justify-content: center;
align-items: center;
}
.row:not(:last-child) {
margin-bottom: 1em;
}
.container {
width: 100%;
}
<div class="container">
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<button>Button</button>
</div>
</div>
While #Gerard's answer does work. It did not for me, on my site. Since I have a bunch of inherited css from code writen years ago. This, however, did work.
.sub-slider {
width: 100%;
display: flex;
flex-flow: column;
}
.slider {
display: flex;
flex-flow: row;
justify-content: center;
align-content: center;
align-items: center;
}
.sub-slider-btn-wrp {
align-self: center;
}
.item {
width: 20%;
height: 50px;
background: blue;
border: thin solid red;
}
<div class="sub-slider">
<div class="slider">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="sub-slider-btn-wrp">
<button>Button</button>
</div>
</div>

Why are these flex items spaced in this way? [duplicate]

This question already has an answer here:
Remove space (gaps) between multiple lines of flex items when they wrap
(1 answer)
Closed 5 years ago.
I have made a simple flexbox jsfiddle To play around with all flexbox values, but stumbled upon something that I can't explain my .item divs are spaced out for some reason and .grid is automatically stretching to full height, I'm not entirely sure why this happens?
HTML
<div class="container">
<div class="grid">
<div class="item red">a</div>
<div class="item yellow">b</div>
<div class="item blue">c</div>
</div>
</div>
CSS
.container {
width: 320px;
height: 480px;
background: black;
padding:15px;
margin: 20px auto;
display: flex;
}
.grid {
background: white;
display: flex;
width: 100%;
justify-content: flex-start;
align-items: flex-start;
flex-direction: row;
flex-wrap: wrap;
}
.item {
width: 100%;
flex-grow: 0;
flex-basis: 100%;
align-self: auto;
align-items: flex-start;
padding: 10px 0;
}
.red { background: red; }
.yellow { background: yellow; }
.blue { background: blue; }
The align-items: flex-start (set on .grid) causes this type of behavior. As specified in the MDN docs
The CSS align-items property defines how the browser distributes space between and around flex items along the cross-axis of their container.
If you disable it, the value will be set to stretch by default (each flex item will be stretched to fill the container).

Is there any use for flex-shrink when flex-wrap is wrap?

I don't think flex-shrink and flex-wrap:wrap; make sense together but I wonder if there is something I'm missing.
.container{
background: #DDD;
width: 300px;
height: 100px;
padding: 20px;
display: flex;
flex-direction: row;
flex-wrap: nowrap
}
.tags{
background: orange;
box-sizing: border-box;
flex: 1 3 200px;
}
.redes{
background: cyan;
box-sizing: border-box;
flex: 0 1 200px;
}
.wrap{
flex-wrap: wrap;
}
<div class="container">
<div class="tags">box1</div>
<div class="redes">box2</div>
</div>
<div class="container wrap">
<div class="tags">box1</div>
<div class="redes">box2</div>
</div>
I understand that when, flex-wrap is set to nowrap, the negative space gets distributed using the values on flex-shrink. Meanwhile, if flex-wrap is set to wrap, there can't be any negative space, can it? Therefor this property is just useless, or at least I can see any effect. Is this right?
Meanwhile, if flex-wrap is set to wrap, there can't be any negative space, can it?
If an element is wider than the flex container, it can't wrap across multiple lines, but it can shrink.
Therefor this property is just useless, or at least I can see any effect. Is this right?
Nope, you'll see the effect when a flex item would otherwise overflow its parent container.
.box {
background-color: pink;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.wide {
background-color: lightgreen;
flex: 0 0 auto;
margin: 10px 0;
width: 150%;
}
.shrink {
background-color: lightblue;
flex-shrink: 1;
}
<div class="box">
<div class="wide shrink">
Wide, shrinks
</div>
<div class="wide">
Wide, won't shrink
</div>
</div>

Resources