Grid with flexible-width aligned elements - css

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 !

Related

Switch flexbox width to 50% when there are 4 child items

I am trying to use flexbox to set up a grid display of images. Everything is working, and the layout looks nice, except when I have 4 images.
This is my current code for the images
section.flex-container .field-items {
display: flex;
justify-content: center;
flex-wrap: wrap-reverse;
align-items: stretch;
}
section.flex-container .field-items .field-item {
display: inline;
flex-grow: 1;
width: 33%;
padding: 10px;
}
Is there any way that I can increase the width to 50% when 4 .field-items are present? Again, I only want the 50% with to occur when there are 4 images.
A demo can be found here on codepen: Demo
You can achieve this via sibling count, which is pretty rad if you've never used it before. You're may already be familiar with the pseudo-class :nth-child which lets you select something based on its position within a list of children.
In comes :nth-last-child. The difference between the two is that
nth-child applies to the nth child counting from the top (ie, the
child that has n-1 elements before it) while the nth-last-child
applies to the nth child counting from the bottom (ie, the child that
has n-1 elements after it!). (Original | Follow-up)
Using the sibling count, you can then increase the width of your .field-item when it has 4 items like so:
section.flex-container {
.field-items{
.field-item {
&:first-child:nth-last-child(4), &:first-child:nth-last-child(4) + .field-item {
width:50%;
}
}
}
}
CodePen

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

Get flexbox column wrap to use full width and minimize height

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;
}

In CSS, is it possible to select the last element before a wrap?

For example,
I have a bunch of div's side by side, and each div has a border-right:1px
The parent element is a certain width so at a certain point, the extra div wraps to the next line.
In essence, I do NOT want a border-right for the last div before the wrap.
If this doesn't make sense, I can create a fiddle. I just want to know can I target that last div before the wrap. (last-child will target the last div that is on the next line which isn't want.)
Figure out how many columns you're getting with the current width, either hardcoded or with JS and then use the nth-child selector.
For example if you have 3 columns per row with each div having a class of col it would be
div.col:nth-child(3n){border-right:none;}
The nth-child selector can be modified depending on however many columns are in each row of divs.
There is no way to select the last item from multiple lines, only the :last-child.
If your elements line up in columns, the multi-column module may be of interest to you. It has a column-rule property that's similar to borders, but only appears vertically between columns, never on the outer edges.
http://cssdeck.com/labs/febtiiet
.container {
columns: 20em;
column-rule: 1px solid;
}
Prefixes may be required: http://caniuse.com/#feat=multicolumn
Otherwise, you will need to switch to placing the border on the left as MrLister suggests:
http://cssdeck.com/labs/f8qjngd4
.container {
overflow: hidden;
padding: 0;
border-style: none;
}
.child {
border-left: 1px solid;
position: relative;
left: -1px;
display: inline-block;
width: 20em;
}

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