I have this at the moment:
.container {
background: gray;
width: 600px;
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
width: auto;
height: auto;
margin: 4px;
flex: 1;
flex-basis: 20%;
}
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
<div class="item">F</div>
<div class="item">G</div>
</div>
What I'm trying to do is have 5 items per row in a flexbox. Currently they don't appear because they don't have a set width/height, which leads me to my next question. Is it possible to auto-resize the items in order for 5 of them to fit per row?
How would I do this?
Thanks!
You are right in giving a flex-basis: 20% but you have to adjust for the 4px margin on each flex item for it to wrap properly.
Equal Width Flex items in the last row
Use flex: 0 1 calc(20% - 8px) - this means the item won't grow beyond 20% of width (adjusting for margin) and can shrink based on the container width. See demo below:
.container {
background: gray;
width: 600px;
height: 200px; /* height given for illustration */
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
margin: 4px;
flex: 0 1 calc(20% - 8px); /* <-- adjusting for margin */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Another approach is a bit hacky - you can keep flex-grow set to one and flex-basis: calc(20% - 4px) using flex: 1 1 calc(20% - 4px), and use a pseudo element that fills the remaining space:
.container {
background: gray;
width: 600px;
height: 200px; /* height given for illustration */
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
margin: 4px;
flex: 1 1 calc(20% - 8px); /* <-- adjusting for margin */
}
.container:after {
content: '';
display: block;
flex: 999; /* grow by a large number */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
If you don't have the n item per row requirement then you can refer this:
Unordered list that acts like grid-auto-flow dense
Flex items in last row expands to fill the available space
If in a row you have less than 5 items and you want them to fill in the remaining space use flex: 1 1 calc(20% - 8px) (note that flex-grow is set to 1 here so that the flex items in the last rows expand to fill the remaining space):
.container {
background: gray;
width: 600px;
height: 200px; /* height given for illustration */
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
margin: 4px;
flex: 1 1 calc(20% - 8px); /* <-- adjusting for margin */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
try below css for five items in each row.
.container {
background: gray none repeat scroll 0 0;
display: flex;
flex-flow: row wrap;
position: relative;
width: auto;
}
.item {
background: blue none repeat scroll 0 0;
flex: 1 1 18%;
height: auto;
margin: 4px;
padding: 20px 0;
width: auto;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I'm using this on a WordPress project, where I have to list articles by categories, nested in columns. I just wrote some css for the responsive layout, so as you decrease the browser width, there are less elements in a row.
.container {
margin: 20px auto;
width: 80%;
min-height: 100px;
display: flex;
flex-flow: row wrap;
}
.item {
margin: 10px;
flex: 1 1 calc(20% - 20px);
background-color: lightgreen;
}
#media screen and (max-width: 1200px) {
.item {
flex: 1 1 calc(25% - 20px)
}
}
#media screen and (max-width: 900px) {
.item {
flex: 1 1 calc(33% - 20px)
}
}
#media screen and (max-width: 750px) {
.item {
flex: 1 1 calc(50% - 20px)
}
}
#media screen and (max-width: 550px) {
.item {
flex: 1 1 calc(100% - 20px)
}
}
<div class="container">
<div class="item"><a>Link1</a></div>
<div class="item"><a>Link1</a></br><a>Link2</a></div>
<div class="item"><a>Link1</a></br><a>Link2</a></br><a>Link3</a></div>
<div class="item"><a>Link1</a></br><a>Link2</a></br><a>Link3</a></br><a>Link4</a></div>
<div class="item"><a>Link1</a></br><a>Link2</a></br><a>Link3</a></br><a>Link4</a></br><a>Link5</a></div>
<div class="item"><a>Link1</a></br><a>Link2</a></br><a>Link3</a></br><a>Link4</a></br><a>Link5</a></br><a>Link6</a></div>
</div>
Here is a possible solution: https://jsfiddle.net/9f955jk2/3/
You have to be aware of margins or paddings, that's why I setted the width to 18%
You can set them to 20% (100%/5 items per row) if you will remove all the margins and paddings.
Also don't forget that border will also take some space.
The container should have 100%, otherwise you have to divide the width by 5 and specify it in pixel for each item and not in %
.container {
width:100%;
}
Related
This question already has answers here:
How to add 1px margin to a flex item that is flex: 0 0 25%?
(4 answers)
Closed 9 months ago.
I would like to display 3 items per row, but I want to include margin and border.
Here's is a simple example, but I need to set valid flex property
.box {
display: flex;
flex-wrap: wrap;
width: 1200px;
}
.item {
display: flex;
border: 1px solid #000;
margin: 5px;
flex: // ???
}
<div class="box">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
As far as I understood your question.
Instead of margin use gap property
.box {
width: 100%;
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.item {
flex: 1;
width: 100%;
height: 200px;
border: 1px solid #000;
}
.item:nth-child(4),
.item:nth-child(5),
.item:nth-child(6) {
flex: 0 1 100%;
}
<div class="box">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I would probably do it like this:
Seeing as you have specified a fixed width-value, you could just make each item have a max-width of 400px - border and margin. However, for a more dynamic layout, you could just use max-width: 1200px on box, so its resizable and responsive.
I prefer to use gap instead of margin in flex-layouts. With this, you can set each items max-width to 33.33% (for a 3 row layout), minus the 5px gap and the 1px border. Also, you don't have to use display: flex on the items, as they are already children of a flex-container (unless you plan to have more content inside them).
This would produce this:
.box {
display: flex;
flex-wrap: wrap;
max-width: 1200px;
flex: 1; /* equal items */
gap: 5px;
}
.item {
border: 1px solid #000;
width: 100%;
max-width: calc(33.33% - 6px);
}
<div class="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
However, this is also achievable by using margin and a fixed width. Then you just have to use the items margin and border in the max-width calculation (5px + 5px + 1px + 1px). Keep in mind when using margin in the layout, its also going to affect the margin between the container and the items - not just the gap between the items.
.box {
display: flex;
flex-wrap: wrap;
width: 1200px;
flex: 1; /* equal items */
}
.item {
border: 1px solid #000;
height: 20px;
margin: 5px;
width: 100%;
max-width: calc(33.33% - 12px);
}
<div class="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
I rather use flex-basis on child.
.box {
display: flex;
flex-wrap: wrap;
width: 1200px;
}
.item {
display: flex;
border: 1px solid #000;
margin: 5px;
flex-basis: 30%
}
<div class="box">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I'm trying to create a HTML page that has 3 rows of 2 cells in each. I want all 6 cells to fill the entire page equally without having to specify a height so that when the browser is re-sized, so to are the cells.
I am trying to use the following flex layout but I'm getting them all in a row.
.outer {
display: flex;
min-height: 100%;
}
.row {
border: 1px solid blue;
display: flex;
flex: 1.0;
flex-grow: 1.0;
}
.item {
background-color: orange;
flex: .5;
flex-grow: 0.5;
border: 1px solid red;
}
<div class="outer">
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
Make the outer wrapper a column flexbox:
add flex: 1 to each row so that the rows share the vertical space,
add flex: 1 to each item so that the columns share the horizontal space,
finished up with height: 100% on both body and html elements (you can also use viewport height to set the min-height) and setting default body margin to zero.
See demo below:
body, html {
margin: 0;
height: 100%;
}
.outer {
display: flex;
min-height: 100%;
flex-direction: column; /* added */
}
.row {
border: 1px solid blue;
display: flex;
flex: 1; /* added */
}
.item {
background-color: orange;
border: 1px solid red;
flex: 1; /* added */
}
<div class="outer">
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
</div>
Is there any way to have wraped items in rows with space between alignment, where last row dont have big gap?
<div fxFlex="row wrap" fxLayoutAlign="space-around">
<my-item *ngFor="let item of items"></my-item>
</div>
Actual behaviour:
I need same "space-between" in last row compared to other rows.
The quickest way to get what you're looking for is to add an empty element after the last visible element:
<!-- your last 3 boxes -->
<div class="gray-box">
(your content)
</div>
<div class="gray-box">
(your content)
</div>
<div class="gray-box">
(your content)
</div>
<!-- an empty box - make sure .transparent has opacity: 0-->
<div class="gray-box transparent"></div>
If you're okay with not using flexbox, display: grid is more along the lines of what you're looking for, where you can define grid sizes more strictly:
display: grid;
grid-template-columns: repeat(4, 25%);
grid-gap: /* gap between your items */
You can use "filler" elements. You need 3 elements at the end of your list which are no visible. Everytime when your row breaks the filler helping to keep the right sizes and spaces.
const addbutton = document.getElementsByClassName('add');
// referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
const addEl = () => {
const newli = document.createElement('li');
newli.textContent = 'new flex child';
const pos = document.querySelector('li.filler');
pos.parentNode.insertBefore(newli, pos.previousElementSibling.nextSibling);
}
addbutton[0].addEventListener('click', addEl);
body {
display: flex;
}
ul {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
padding: 0;
flex: 1;
}
ul>li {
flex: 0 1 24%;
background: #ccc;
display: block;
height: 40px;
margin-bottom: 20px;
}
ul>li.filler {
height: 0;
padding: 0;
}
button {
background: #333;
color: white;
border: none;
padding: 5px;
flex: 0 0 100px;
height: 100px;
margin: 10px;
}
<button class="add">click here to add childs</button>
<ul>
<li>lorem</li>
<li>lorem</li>
<li>lorem</li>
<li>lorem</li>
<li>lorem</li>
<li>lorem</li>
<li class="filler"></li>
<li class="filler"></li>
<li class="filler"></li>
</ul>
I'm just guessing on your html and css structure here, but I assume you have something like this:
.wrapper {
width: 1000px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item {
background: gray;
width: 200px;
height: 100px;
border: 1px solid black;
}
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
You can keep the same spacing around each element by using a simple margin and setting the justify-content attribute to either center or flex-start based on your needs.
.wrapper {
width: 1000px;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.item {
background: gray;
width: 200px;
height: 100px;
border: 1px solid black;
margin: 0 20px;
}
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I have a problem with flex-wrap property of a flexbox.
Here is my code:
.container {
display: flex;
flex-wrap: wrap;
}
.item {
width: 50%;
margin: 0 10px;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
</div>
What I want to do is to let some space margin between items but without wrapping them. I want them horizontally two by two and every item with width of 50% margin included to prevent flex-wrap.
.container {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 1 0 34%; /* fg, fs, fb */
margin: 10px;
height: 50px;
background-color: gray;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
With flex-grow: 1 defined in the flex shorthand, there's no need for flex-basis (width) to be 50%, which results in one item per row due to the margins.
Since flex-grow will consume free space on the row, flex-basis only needs to be large enough to enforce a wrap.
In this case, with flex-basis: 34%, there's plenty of space for the margins, but not enough space for a third item on each line.
You can use calc for this, so for example you can set flex-basis: calc(50% - margin x 2).
.container {
display: flex;
flex-wrap: wrap;
}
.item {
flex-basis: calc(50% - 20px);
margin: 10px;
background: lightblue;
height: 50px;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
You may use calc to exclude margin from the width:
.container {
display: flex;
flex-wrap: wrap;
}
.item {
width: calc(50% - 20px);
margin: 5px 10px;
height:20px;
background:red;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 5 years ago.
I need a grid where I only specify the minimum width of the items.
Here is my attempt using flex-wrap and flex-basis: https://jsfiddle.net/2z9pgjfg/1/
HTML:
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
CSS:
.container {
display: flex;
flex-wrap: wrap;
}
.item {
background-color: red;
border: 1px solid black;
flex: 1;
flex-basis: 150px;
}
.item:after {
content: "";
display: block;
padding-bottom: 75%;
}
I want any items in the last row to be the same size as all the others. Is there a way to achieve this without media queries?
Set flex grow to 0.
.container {
display: flex;
flex-wrap: wrap;
}
.item {
background-color: red;
border: 1px solid black;
flex: 0;
flex-basis: 150px;
}
.item:after {
content: "";
display: block;
padding-bottom: 75%;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>