flex-wrap in column direction flex - Container not adapting the width [duplicate] - html

This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed last year.
I don't know what silliness I've got myself into but I'm stuck in a common flexbox issue..
Here's a pen.. https://codepen.io/webdev51/pen/zYPWwbd
What I'm trying to achieve is the parent flex div to be adapting the width when flex item go into 2nd row using flex-wrap.
Desired/expected result:
Results I get:
And here's the most important part that is driving me nuts.
If I replicate the same in flex-direction: row; , it'll be working as expected and whenever the items drop in the next row, the container will adapt the height accordingly.

after changing display: inline-flex to display: flex, add align-content: flex-start;
.spaceship-group{
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 90vh;
align-content: flex-start;
justify-content: center;
position: relative;
border:2px solid orange;
}
.spaceship {
height: 240px;
width: 290px;
position: relative;
border:1px solid blue;
}
<div class="spaceship-group">
<div class="spaceship"></div>
<div class="spaceship"></div>
<div class="spaceship"></div>
<div class="spaceship"></div>
<div class="spaceship"></div>
</div>

Related

Flex wrap column: fill the available width with columns

I have items of different sizes in the flex container which I want to display in several columns of different widths, depending on the content. flex-flow: column wrap works good for me with fixed container height but I have fixed width for container and want the height depending on the content. I.e. I want as many columns as fit in width.
Example, how it must look:
.container {
height: 80px;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-flow: column wrap;
align-content: left;
}
.container > span {
margin: 3px 12px;
background: #ebd2b5
}
<div class="container">
<span>Apple</span>
<span>Apricot</span>
<span>Avocado</span>
<span>Banana</span>
<span>Bilberry</span>
<span>Blackberry</span>
<span>Blackcurrant</span>
<span>Blueberry</span>
<span>Boysenberry</span>
<span>Currant</span>
<span>Cherry</span>
<span>Cherimoya</span>
<span>Cloudberry</span>
<span>Coconut</span>
</div>
Any solutions with CSS?
No. With pure css you can't.
However if you use align-content: stretch; You can distribute the current columns to the entire container width.
.container {
height: 80px;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-flow: column wrap;
align-content: stretch;
}
.container > span {
margin: 3px 12px;
background: #ebd2b5
}
<div class="container">
<span>Apple</span>
<span>Apricot</span>
<span>Avocado</span>
<span>Banana</span>
<span>Bilberry</span>
<span>Blackberry</span>
<span>Blackcurrant</span>
<span>Blueberry</span>
<span>Boysenberry</span>
<span>Currant</span>
<span>Cherry</span>
<span>Cherimoya</span>
<span>Cloudberry</span>
<span>Coconut</span>
</div>

Center a flex item when its siblings have different widths [duplicate]

This question already has answers here:
Keep the middle item centered when side items have different widths
(12 answers)
Closed 5 years ago.
I know flexbox offers a great solution for centering items. But I run into an issue when I have 3 items and I'd like the center (2nd) item to be centered with respect to the window, regardless of the size of the other 2 items.
In my pen you can see the second item "Client Index" is off-center because the content on the right is larger than the content on the left. How can I force it to center itself?
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
<div class="flex">
<span style="font-size:12px;">small</span>
<span style="font-size:20px;">Client Index</span>
<span style="font-size:18px;">Lots of content that moves the center</span>
</div>
My Codepen
One way would be to set flex-grow: 1; flex-basis: 0 so the 3 columns are distributed evenly, then you can center the text or the content in the middle one.
I'm using text-align to center the middle column. You could also use display: flex; justify-content: center; to do the same thing.
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex > span {
flex: 1 0 0;
}
.flex > span:nth-child(2) {
text-align: center;
}
<div class="flex">
<span style="font-size:12px;">small</span>
<span style="font-size:20px;">Client Index</span>
<span style="font-size:18px;">Lots of content that moves the center</span>
</div>
Use nested flex containers and auto margins.
.flex-container {
display: flex;
}
.flex-item {
flex: 1;
display: flex;
justify-content: center;
}
.flex-item:first-child>span {
margin-right: auto;
}
.flex-item:last-child>span {
margin-left: auto;
}
/* non-essential */
.flex-item {
align-items: center;
border: 1px solid #ccc;
background-color: lightgreen;
height: 40px;
}
<div class="flex-container">
<div class="flex-item"><span>short</span></div>
<div class="flex-item"><span>medium</span></div>
<div class="flex-item"><span>lonnnnnnnnnnnnnnnnnnnng</span></div>
</div>
Here's how it works:
The top-level div is a flex container.
Each child div is now a flex item.
Each item is given flex: 1 in order to distribute container space equally.
Now the items are consuming all space in the row and are equal width.
Make each item a (nested) flex container and add justify-content: center.
Now each span element is a centered flex item.
Use flex auto margins to shift the outer spans left and right.
You could also forgo justify-content and use auto margins exclusively.
But justify-content can work here because auto margins always have priority. From the spec:
8.1. Aligning with auto
margins
Prior to alignment via justify-content and align-self, any
positive free space is distributed to auto margins in that dimension.

CSS flexbox wrap not resizing to fit contents [duplicate]

This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
Closed 3 years ago.
A simplified plunkr to show the problem:
https://plnkr.co/edit/mHTHLEumQ04tInFVAz3z?p=preview
If you resize the right viewport until the two containers no longer fit on the same row, right one moves to a new line.
However the parent inline-flex container width does not change, throwing the top "header" element off - the "button" in "header" should be right aligned with the last item in the container below.
The two (or more) items have fixed width but no space between them. Those are the only elements with fixed width or height.
How can I force the flex container width to fit/shrink when items wrap to a new row (without using js, pure HTML/CSS)?
.main-flex {
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.flex-container {
flex-grow: 1;
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: row;
flex-direction: row;
flex-wrap: wrap;
}
<div style="margin-top: 100px;" class="main-flex">
<div>
<span>header</span>
<span style="float:right">button</span>
</div>
<div class="flex-container">
<div style="height: 400px; width:250px; border: 1px solid black;"></div>
<div style="height: 400px; width:250px; border: 1px solid black;"></div>
</div>
</div>
In CSS, the parent container doesn't know when its children wrap. Hence, it continues scaling its size oblivious to what's going on inside.
Put another way, the browser renders the container on the initial cascade. It doesn't reflow the document when a child wraps.
That's why the container doesn't shrink-wrap the narrower layout. It just continues on as if nothing wrapped, as evidenced by the reserved space on the right.
More details here: Make container shrink-to-fit child elements as they wrap
But you don't need the container to shrink for your layout to work. It can be built with a few adjustments to your HTML and CSS.
.main-flex {
display: inline-flex;
flex-wrap: wrap;
}
.flex-container {
display: flex;
flex-direction: column;
}
.flex-container>div {
height: 400px;
width: 250px;
border: 1px solid black;
}
.flex-container:nth-child(2)>span {
align-self: flex-end;
}
<div class="main-flex">
<div class="flex-container">
<span>header</span>
<div></div>
</div>
<div class="flex-container">
<span>button</span>
<div></div>
</div>
</div>
revised demo

using a flex item as a flex container

I wanted to use flexbox with a column layout, but I wanted the top n - 1 flex items to be pinned to the top and the nth flex item to be pinned to the bottom of the main flex container area.
I solved this by using the nth flex item to also be a new flexbox/flex container using justify-content: flex-end, but I couldn't find any examples that were doing this - so is this a correct/acceptable solution according to the standard and, if not, how would I otherwise go about this with flexbox?
Here's a quick example:
.flex-container {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
width: 300px;
height: 240px;
background-color: Silver;
}
.flex-container-bottom {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
width: 300px;
height: 240px;
background-color: orange;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.flex-item {
background-color: DeepSkyBlue;
width: 100px;
height: 100px;
margin: 5px;
}
.flex-item-bottom {
background-color: red;
width: 100%;
height: 50px;
}
<div class="flex-container">
<div class="flex-item">flex item 1</div>
<div class="flex-item flex-container-bottom">
<div class="flex-item-bottom">flex item 2</div>
</div>
</div>
The spec isn't very clear on this, but it states that "Each in-flow child of a flex container becomes a flex item, and each contiguous run of text that is directly contained inside a flex container is wrapped in an anonymous flex item." This seems to imply that if I put a flex container inside another flex container that the inner flex container would also implicitly become a flex item for its containing flex container even if this is not explicitly defined. Example 1 of the specification shows a flex container within a flex container and assuming it is legal syntax it follows that my use case may also be legal, but the section with example 1 is marked as non-normative... (╯°□°)╯︵ ┻━┻... At this point I'm just going to assume this is correct.
It's hard to say that your use of flex-end is wrong because you're getting the desired effect, but there's an easier way to do it.
Try using:
.flex-container{
display: flex;
justify-content: space-between;
flex-direction: column;
}
justify-content: space-between; forces your flex items to spread out as much as possible in the flex container.
This is the reference guide I use whenever doing anything with flexboxes:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
You can also try this this will make your last item to stick to bottom of your parent container
.flex-container{
position:relative;
}
.flex-item-bottom{
position:absolute;
bottom:0;
}

Fill both vertical and horizontal space using flexbox

I have a web interface with several boxes of indeterminate height and fixed width (33.3%) which are arranged in a flexbox. I would like to fill the entire space before creating a new row, unlike my example does:
http://jsfiddle.net/dshb0eaw/1/
HTML:
<div class="flex container">
<div class="flex item">First box</div>
<div class="flex item">Second box</div>
<div class="flex item three">This box is higher than the others</div>
<div class="flex item">Another box in the next row - can I get this one below box one?</div>
</div>
CSS:
* {
box-sizing: border-box;
}
.flex.container {
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
width: 250px;
border: 1px solid green;
align-items: flex-start;
-webkit-align-items: flex-start;
}
.flex.item {
flex: 1 0 auto;
-webkit-flex: 1 0 auto;
border: 1px solid red;
width: 33.3%;
max-width: 33.3%;
}
.flex.item.three {
height: 250px;
}
I read about some workaround with multiple wrapper containers, one for the vertical and one for the horizontal filling, but I'm not sure if this could work for me, since my boxes are of indeterminate height when I create them and their height might change during usage.
I know there are JavaScript-based solutions like masonry, which I already tried, but I wonder if there are CSS-only solutions to this.