Get flexbox column wrap to use full width and minimize height - css

I have a container with a fixed width and variable height. I'm filling the container with an unknown amount of elements.
I'd like the elements to arrange themselves in columns, from top to bottom and then left to right.
I could use column, but I don't know the maximum width of the child elements, so I can't set a column-width or column-count.
I think display: flex with flex-flow: column wrap is the way to go, but if I maintain height: auto on the container, it will generate as a single column without wrapping elements to use all the available width.
Can I convince flexbox to use all the available width and thus minimize the container's height?
Would you suggest a different solution?
Fiddle: http://jsfiddle.net/52our0eh/
Source:
HTML:
<div>
<span>These</span>
<span>should</span>
<span>arrange</span>
<span>themselves</span>
<span>into</span>
<span>columns,</span>
<span>using</span>
<span>all</span>
<span>available</span>
<span>width</span>
<span>and</span>
<span>minimizing</span>
<span>the</span>
<span>container's</span>
<span>height.</span>
</div>
CSS:
div {
outline: 1px solid red;
width: 100%;
display: flex;
flex-flow: column wrap;
align-items: flex-start;
/*height: 8em;*/
}
span {
outline: 1px solid blue;
}

What you look for is more like the column rules: DEMO
div {/* do not set column numbers rule */
width: 100%;
-moz-column-width:4em;
column-width:4em;
-moz-column-gap:0;
column-gap:0;
-moz-column-rule:solid 1px;
column-rule:solid 1px;
text-align:center;
}

I've compromised and set height: 10em (which seems acceptable) along with overflow-y: auto (to add a horizontal scrollbar in case of overflow) on the container element.
I would still like to know if there is a way to use all available width and minimize the height, though.

In the end, your options for overflowing are hide, scroll, or wrap. How about this version instead? It takes any overflowing items and puts them on a second row. Items on the second row still fill the available space, but are larger due to the smaller number of items sharing the space.
http://jsfiddle.net/52our0eh/14/
div {
outline: 1px solid red;
display: flex;
flex-flow: row wrap;
}
span {
outline: 1px solid blue;
flex:1;
}

Related

How to make a div fixed when using justify-content space between

I am trying to add two divs(left-item-container, right-item-container) to the top of my page and make the left-item-container fixed . I wish to have the left item fixed when the page is scrolled . The right item should be scrolled and can be hidden.
I would also like to have space between the divs.
.mydiv{
display:flex
justify-content: space-between;
.left-item-container{
position: fixed;
}
.right-item-container{
}
}
When I exclude position fixed the space between works fine - however I loose the fixed position.
I need help to make the left item fixed and also have space between when both divs are visible.
I was able to get it to work by giving the container a specific height as well as applying a justify-content of flex-start to the left-container as that is where we'd like it to stay fixed.
.mydiv{
display:flex;
justify-content: space-between;
.left-item-container{
border: 10px solid red;
justify-content:flex-start;
position:fixed;
height:30px;
}
.right-item-container{
border:10px solid blue;
height:20px;
}
}
Check out this jsfiddle

CSS Flex Column Layout without Specified Height

Just discovered flex today and I'm hoping it'll solve a small visual challenge.
I have a list of items already alphabetically sorted. They all have the same width and, up until now, I've had them floating left. This results in a left-to-right order with wrapping when horizontal space runs out.
What I was hoping to do is have top-down sorting with as many columns as possible with the available width. Seeing as this list is dynamic, the height would be variable. And the height would have to increase as horizontal space is lost (resizing) preventing as many columns.
Given the apparent nature of what flex is trying to accomplish I'd think this would be supported, but thus far I can't figure it out. "display: flex" and "flex-flow: column wrap" seem correct, but it requires a specific height to work, which I can't provide.
Am I missing something?
Edit:
I've created a JSFiddle to play with here: https://jsfiddle.net/7ae3xz2x/
ul {
display: flex;
flex-flow: column wrap;
height: 100px;
}
ul li {
width: 150px;
list-style-type: none;
border: 1px solid black;
text-align: center;
}
If you take the height off the ul, nothing wraps.
It seems the conceptual problem is that "column" flow is all tied to the height of the container instead of to the width, which is what I want. I don't care how tall the area has to be. I care about having as many columns as possible in the available width. Maybe this is just an annoying shortcoming of the flex convention.
This seems like a job for CSS columns: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Columns
Instead of flex, give the ul a column-width CSS rule:
ul {
column-width: 150px;
}
Here's a JSFiddle.
I'm not sure if this is what you're looking for, but you might need to change flex-flow: column wrap: to flex-flow: row wrap; and change the height and width to 100vh and 100vw
ul {
display: flex;
flex-direction: column;
flex-flow: row wrap;
height: 100vh;
width: 100vw;
}
So now the list items keep the same width and adjust height based on the size of the view width. Updated Fiddle

Grid with flexible-width aligned elements

I've been trying to make a responsive grid layout that contains a set of flexible elements without having to put media queries for each order of width.
Basically, here are the "rules" of the grid:
The elements have a minimum width, but are able to take available space
The layout will place as much elements as possible on a row. The remaining space will be split among the elements.
The last elements (on the last and possibly unfilled row) have the same width as the elements on the previous rows.
I managed to do one system that nearly works with flexbox.
The only problem is that the last element takes all available space instead of being aligned with the previous elements.
#b {
border: 1px solid black;
display: flex;
flex-wrap: wrap;
}
#b div {
border: 1px solid red;
flex-grow: 1;
flex-basis: 200px;
display: inline-block;
}
Is there a way to do that with only CSS ?
Thanks in advance !

Force flex element not to grow in cross-axis direction

I'm making a page with a vertical menu using display: flex;. I want the menu's width to fit snuggly around a few buttons, without having to use a fixed width.
However, I also want the menu box to have a status message, which can have quite a long text. I'd like this status-div to have the width of the menu, while not forcing the menu container to grow its width. Instead, the status-div should grow its height and wrap the text.
Explaining this in words is pretty difficult, so I suggest you checkout out this fiddle: http://jsfiddle.net/bXL3q/
Note the difference when setting .statusmessage to display: none;.
Any ideas, or is what I'm trying to do not feasible? ..should it be?
What I've tried:
width: 100% fails, obviously it just assumes the parent width
width: -webkit-min-content sort of works, but it makes the element too narrow
flex-basis and flex-grow affect the height of the element, and do nothing to affect the width
position: absolute will solve the width issues, but now I have no way to define the height of the status-div.. (for the purpose of forcing a scroll bar in windows with small height - instead it will just flow over the button elements)
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-flow: row nowrap;
align-items: stretch;
}
.page {
flex-grow: 1;
background-color: yellow;
}
.menu {
background-color: red;
height: 100%;
display: flex;
flex-flow: column nowrap;
}
.somechildren {
white-space: nowrap;
background-color: green;
border: 1px solid black;
}
.menu>* {
flex-shrink: 0;
}
.separate {
flex-grow: 1;
}
.statusmessage {
background-color: magenta;
align-self: flex-end;
/*display: none;*/
}
<div class=menu>
<div class=somechildren>I'd like the menu's</div>
<div class=somechildren>width to fit nicely</div>
<div class=somechildren>around these children</div>
<div class=separate></div>
<div class=statusmessage>
While forcing this status message to wrap and grow its height, without affecting the width of the container.
</div>
</div>
<div class=page>
The page
</div>
You were almost there with width. What you need to do is set width and min-width (demo):
.statusmessage {
width:0; /* Collapses .statusmessage so it doesn't affect column width */
min-width:100%; /* Expands .statusmessage to width of column */
}
The width can be (and probably should be) set to a value other than 0. It should just be the minimum width of the column or smaller. So use a value that works for you.
I've tested this on Chrome and Firefox and seems to work in both. Now, is it supposed to work? I'm not sure, I haven't read into the spec that much (it could be undefined). Make sure to test in all browsers you need it to work in. (And check the spec to see if this behavior is undefined/incorrect.)
width: 0; min-width: 100%; didn't work for me.
Instead, I set
position: relative;
on the flex child and wrapped its contents in an inner div with
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
This prevents the contents from contributing to the flex container size while still matching the cross-axis size determined by the rest of the flex children.
For me, the issue was that the default value of align-items is stretch. So the items stretch out the cross axis by default.
You can either set align-items: flex-start or align-self: flex-start for the single flex child.
The visual here is quite illustrative.

Automatic cell width on table-layout fixed, but the last cell

I want to create a breadcrumb for a website.
The elements should expand to fill all of the available space. If they couldn't fit on it, I'd like to have their inner text clipped with text-overflow: ellipsis, except the last one.
In other words: have the last element with the full width, and distribute the other ones on the remaining space (with width depending on their content, or if not possible at least they should't look bad...).
I tried with this code.
<div>
<ul>
<li>paka</li>
<li>ultrapaka</li>
<li>ultrapaka</li>
<li>ultrapaka ultrapaka</li>
<li>daslidjsajdsa</li>
</ul>
</div>
Here the CSS:
div {
display: table;
margin: 5px;
border:1px solid #777;
padding: 3px;
table-layout:fixed;
}
ul {
display: table-row;
}
li {
display: table-cell;
padding: 5px;
border: 1px solid #000;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
If I put table-layout: fixed the table really constrains its space, but I lose the automatic cell width.
If I don't put it, the table just overflows outside of its limits.
You can find a JsFiddle here. (I have set the table width to 400px to show the desired effect, even though on the final solution it should expand at 100%).
The best way to do that is using flexbox properties, but it's hard to make it work for all browsers.
You could maybe give a fixed width or percentage for all cells, and use the :last-child selector to apply an auto width on the last cell.
You could also try box-sizing, but I'm not sure about the result.

Resources