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

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

Related

Flex left div fill remaining space when right div is at maximum width

I have two divs inside a flex box. Div A is on the left, and div B is on the right.
I would like div A to take up 60% of the flex box, and div B to take up 40% of the flex box. As you can imagine, my css will look like this:
.container {
display: flex;
justify-content: start;
flex-direction: column;
}
.div_a {
width: 60%;
}
.div_b {
width: 40%;
}
Also, the browser will look like this:
Now, I would like div B to have a maximum and minimum width, the code will now look like this:
.container {
display: flex;
justify-content: start;
flex-direction: column;
}
.div_a {
width: 60%;
}
.div_b {
width: 40%;
max-width: 768px;
min-width: 480px;
}
Unfortunately, this will lead to this situation large browsers.
When Div B has reached its maximum width, I would like div A to fill up the rest of the space, like this:
Any ideas or fixes would be appreciated, thank you very much in advance.
I should mention that min-width: 60% for Div A produces the same situation, unfortunately.
This is a perfect case where you would turn towards the property flex-grow.
Since you're working with a 60%/40% size, you can use flex-grow:6 and flex-grow:4, or alternatively: flex-grow:3 and flex-grow:2. Or even: flex-grow:1.5 and flex-grow:1 since the property also accepts decimals!
.div_a {
flex-grow:3;
}
.div_b {
flex-grow: 2;
max-width: 768px;
min-width: 480px;
}
flex-grow is a property that will tell the parent (flexbox) to divide the available width into whatever the sum is of the amount of flex-grow specified in its child elements. By limiting the max width of .div_b, you tell flexbox to stop increasing the width after it reached that max, and the remaining width will be reserved for the other elements (.div_a in this case).
Also
I do want to point out that you're using flex-direction:column, but you're trying to create a row based layout. It's a better idea to use flex-flow: row nowrap. Which is a shorthand to declare both flex-direction and flex-wrap together and, with the value row nowrap will tell the parent to force everything on one line in a horizontal layout.
.container {
display: flex;
justify-content: start;
// flex-direction: column;
flex-flow: row nowrap;
}

How do I 'merge' items within a flexbox, so they don't overflow?

I'm trying to make my personal website responsive. On the landing page (in desktop view) there are three links arranged in a flex box row. Each link itself is also a flexbox, with the items arranged in a column:
The CSS for this is as follows:
//Parent container:
.homemain-links {
display:flex;
flex-direction: row;
justify-content: space-between;
margin-top: 10%;
}
//Link:
.info-container {
display:flex;
flex-direction: column;
align-items: center;
padding:10%;
width:100px;
height:100px;
box-sizing: border-box;
}
When the screen size shifts from desktop to mobile, I want the links to switch from a row to a column. However when this happens, the link contents spill out:
CSS:
#media (max-width:576px) {
.homemain-links{
display:flex;
flex-direction: column;
}
.info-container {
width:100px;
height:100px;
}
}
I've tried using width:auto height:auto which worked, but the div container switched from a square to a rectangle, and I'm wanting to retain the square shape.
So is there a way to 'merge' a flexbox with the items within in, so that the items stay within it's boundaries?
As far as I know, no, the reason they spill out of the div container is because you have set a fixed width/height. You can try to set it with a relative values that's equal in order to have it adapt to screen sizes as well as retain the square shape, i.e., 6.5rem for both width/height or other similar relative values in CSS.

Flexbox - Variable Number of Columns Problem

I'm trying to aim for a responsive design wherein a long list of links is arranged in columns, the number of columns varying according to the width of the display device screen. As I understand it, I must specify the height of the container to get multiple columns. However, then the columns continue to the right off the screen. I do not know the length of the links. Is there any way to do this through Flexbox? It seems like such an obvious requirement.
The CSS I have so far is:
/* Container */
.links {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 100vw !important;
height: 90vh;
}
/* Links in Container */
.links a {
white-space: nowrap;
flex: 1;
margin: 5px 5px 0 20px;
}
Edit: this it NOT a duplicate as commented. The problem not that the container width doesn't grow horizontally. The problem is that it DOES grow horizontally, not vertically.
Have you considered just using CSS Columns?
You wouldn't need to specify any height and then as the screen width changes, the number of columns will adjust based on the width you specify - taking up whatever height it needs, accordingly.
Your CSS could just look like this:
.links {
columns: 5 100px; // # of columns | minimum column width
column-gap: 40px; // space between columns
}
.links > a {
display: block;
padding: 10px 5px;
}
<div class="links">
link1
link2
link3
link4
link5
link6
link7
link8
link9
link10
link11
link12
link13
link14
link15
link16
link17
link18
link19
link20
</div>
Browser support for columns is pretty good.
Hope this helps!

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 !

CSS3 flex-box property

I wanted to use flex box property to my layout where we create boxes dynamically.
So I want to adjust themselves(box) as per the count. Like if only 1 box is there, it should take complete 100% space and max 3 boxes will come in one row.
If 4th box comes in the screen then go to the next row automatically.
I have searched a lot about flex-flow but did not get the right solution.
Please help.
Regards
Using new syntax, Chrome (requires prefix) and Opera only at present:
#container {
display: flex;
flex-flow: row wrap;
}
#container > * {
flex: 1 1 33%;
}
Here is a demo: http://jsfiddle.net/lpd_/qwwT8/. If you don't want items on subsequent rows to stretch once the first row is filled, you can add:
#container > *:nth-child(n+4) {
max-width: 33.33%;
max-width: calc(100% / 3); /* To override and be more precise, if you wish */
}

Resources