Given this CSS:
div.container {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
border: 1px solid blue;
}
div.container div {
width: 200px;
border: 1px solid gray;
display: inline-block;
text-align: center;
}
This layout has the first item in each row aligned to the left, and the last item aligned to the right, as required.
As the browser window is made narrower, the distributed div elements will move closer together until they touch, at which point they are re-arranged over an additional row. Again, the first div on each row is aligned left, and the last aligned right with space between.
Is there any way of setting a minimum spacing so that the inner div elements always have a gap between them.
padding and margin will probably not work, as the alignment
<-- 1st left in row and last right in row --> will not hold.
Bit late the the party but I ran into the same issue. The way I solved it probably wont work for everyone but here it is for those who can use it.
The basic idea is that you have a min gap of x. You set the left and right margins of each item to x/2 so that the distance between the items will be x (margin + margin). Then you wrap all of the items in a container with a left and right margin of -x/2. This will hide the margin on the items at the edges of each row.
Here is a working example:
.box {
border: 1px solid black;
overflow-x: hidden;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 0 -1em;
}
.item {
display: flex;
border: 1px solid grey;
padding: 1em;
width: 20%;
margin: 0 1em;
}
<div class="box">
<div class="container">
<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>
</div>
The overflow-x: hidden; on .box is to prevent the horizontal scrollbar that shows up in some browsers because of the margin overflowing.
If you want the gap to always be consistent and for rows with only one item to have that item span the whole row then you can add flex-grow: 1 to .item.
You can add another div with flex style for holding the needed gap between inner divs. and for the minimum width for that gap use this property (as mentioned in W3Schools.com):
flex: flex-grow flex-shrink flex-basis|auto|initial|inherit;
which flex-shrink is :
flex-shrink: A number specifying how much the item will shrink relative to the rest of the flexible items
so, for example you set this css code for the gap div :
flex: 1 0 10px;
that tells gap div will have 10px width, and will grow relative to the rest of the flexible items, but WON'T SHRINK. so the minimum width will be 10px at the narrowest width of the screen.
In 2022 you can just use gap CSS property:
div.container {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
border: 1px solid blue;
gap: 20px;
}
To support older browsers you may use margin hack.
div.container > * {
margin: 12px 0 0 12px;
}
div.container {
display: inline-flex;
flex-wrap: wrap;
margin: -12px 0 0 -12px;
width: calc(100% + 12px);
}
Since April 2021 support for flexbox-gap has arrived in all major browsers (IE considered dead). Combining it w/ space-between solves your problem.
div.container {
display: flex;
gap: 10px; /* minimum gap between flex-items */
justify-content: space-between;
}
It's a couple of days passed since this question was asked, but I thought I should add my solution if anybody comes past and has the same issue.
I suggest using calc, width, and media to solve this issue. Yes, it's a little work but it's a visual clean solution in my opinion.
.main{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.main > div{
width: 100%;
height: 125px;
border: 1px solid red;
}
#media (min-width: 576px) {
.main > div{
width: calc(100% / 2 - 5px);
margin-bottom: 5px;
}
}
#media (min-width: 992px) {
.main > div{
width: calc(100% / 3 - 5px);
}
}
#media (min-width: 1140px) {
.main > div{
width: calc(100% / 6 - 5px);
margin-bottom: 0;
}
}
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
For the needed breakpoints I calculate the width I want the divs to use and subtract the space I want them to have.
I hope this helps someone and that I explained it understandable.
Regards.
Setting a flex-basis with percentage also will do the trick. Then the min space between will be also in percentage.
For instance, with 3 elements, flex: 0 0 30% will allow a fixed 10% space reparted between elements.
with 6 elements, flex: 0 0 15% and so on.
Related
I am constructing a form where the field's width percentage is dynamically set by clients.
My first approach was to create a flex container with wrapping enabled and space the fields evenly using gap: 16px. To my surprise, flex-wrap and gap don't behave as I would expect.
main {
width: 400px;
background-color: gray;
display: flex;
gap: 16px;
flex-wrap: wrap;
}
div {
background-color: blue;
}
.first {
width: 50%;
}
.second {
width: 50%;
}
<main>
<div class="first">First</div>
<div class="second">Second</div>
</main>
I expected them to be in the same line and have the gap in-between. This happens when I remove the flex-wrap.
The only solution I found was to use calc(50% - 16px), but this is far from ideal. Maybe I'm approaching the problem wrongly?
I'm having a problem with CSS flexbox. I had a working code yesterday yet today when I tested my solution it stopped working for some reason. It has to do with flexbox.
This is the result I want to have:
To be able to position the content with justify-content. This fails
Content should take all the available space so it has flex-grow: 1. This fails, as well.
The footer should be at the bottom since the content would push it down by taking all the available space thanks to flex-grow: 1. This fails.
It seems that whole flexbox stopped working correctly for me.
I believe the problem is that for some reason flexbox does not even respond correctly to this:
`justify-content: flex-start`
If I try any other values there like center, flex-end, etc nothing happens.
Funny thing is that yesterday flexbox was behaving correctly, I could position it around with justify-content and today I can't.
What am I missing here why is not at least justify-content: flex-end or justify-content: center doing behaving correctly and positioning the content?
If I fix the problem that causes justify-content to stop working I believe flex-grow will also work.
Does anyone have an idea why it's misbehaving?
I can get flex to behaving using this playground so I know my code should be working, My code above is exactly what I did here in the playground:
https://demos.scotch.io/visual-guide-to-css3-flexbox-flexbox-playground/demos/
.ikigai {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.header, .footer {
height: 80px;
margin: 10px;
border: 1px dashed lightgray;
}
.content {
margin: 10px;
border: 1px dashed lightgray;
flex-grow: 1;
}
<div class="ikigai">
<div class="header">this is a header</div>
<div class="content">content</div>
<div class="footer">footer 12</div>
</div>
https://jsfiddle.net/re01pn2x/
Your flex container has no height defined.
Therefore, it defaults to height: auto (content-driven height).
Add this to your code:
.ikigai {
height: 100vh;
}
.ikigai {
display: flex;
flex-direction: column;
/* justify-content: flex-start; */ /* default value; not necessary */
height: 100vh;
}
.header, .footer {
height: 80px;
flex-shrink: 0; /* optional; if you don't want items to shrink vertically */
margin: 10px;
border: 1px dashed lightgray;
}
.content {
margin: 10px;
border: 1px dashed lightgray;
flex-grow: 1;
}
body {
margin: 0; /* override default margins; prevents vertical scrollbar */
}
<div class="ikigai">
<div class="header">this is a header</div>
<div class="content">content</div>
<div class="footer">footer 12</div>
</div>
More details: How to make div 100% height of the browser window?
justify-content
Note that justify-content wasn't working in your code because there was no free space available. This property works by distributing free space in the container. In this case, because the container was defaulting to height: auto, there was only enough space to accommodate the content.
justify-content & flex-grow
Also note that even with a height defined that creates extra space, justify-content will not work if you use flex-grow. Why? Because flex-grow will consume that free space, again leaving no space for justify-content to distribute.
You can fixed using height:100vh;
.ikigai {
display: flex;
flex-direction: column;
justify-content: flex-start;
height: 100vh;
}
.header, .footer {
height: 80px;
margin: 10px;
border: 1px dashed lightgray;
}
.content {
margin: 10px;
border: 1px dashed lightgray;
flex-grow: 1;
}
I was using CSS-Grid to make a list of elements that had a min-width of 35px and the size would adapt if you resized the window, so that always as many elements as possible could fit into one row, and the gap on the right of the row would always be the same as it was on the left using this CSS:
article{
display: grid;
grid-template-columns: repeat(auto-fill, minmax(35px, 1fr));
grid-gap: 5px;
}
div{
height: 35px;
background-color: lightblue;
}
You can try it here, by rescaling the window.
https://jsfiddle.net/k36jy0ou/39/
But due to compability problems I now want to make the same behaviour using flexbox. I don't know flexbox really well, but I got kind of close using this CSS:
article{
display: flex;
flex-wrap: wrap;
}
div {
flex-grow: 1;
min-width: 35px;
max-width: 40px;
background-color: lightblue;
height: 35px;
margin: 5px;
}
https://jsfiddle.net/k1tmfu7o/3/
Except, that not all elements have the same size, if you do it like this.
Here is an image to explain my problem
Is there any way to do it using flexbox?
Thank you for your help.
Already has an answer here
Working example from the answer above
SASS code
=flex-wrap-fix($flex-basis, $max-viewport-width: 2000px)
flex-grow: 1
flex-basis: $flex-basis
max-width: 100%
$multiplier: 1
$current-width: 0px
#while $current-width < $max-viewport-width
$current-width: $current-width + $flex-basis
$multiplier: $multiplier + 1
#media (min-width: $flex-basis * $multiplier)
max-width: percentage(1 / $multiplier)
ul
display: flex
flex-wrap: wrap
li
// I want the width to be between the following two sizes
min-width: 40px
//max-width: 100px
// this keeps all the elements the same size
// **as long as they are on the same row**
// but I want them to all the same width everywhere
//flex: 1 0 0
+flex-wrap-fix(100px)
// demo styles
ul, li
margin: 0
padding: 0
list-style: none
ul
background-color: tomato
li
.content
margin: .5em
background-color: darkgreen
// the image may have variable width, I want it to take the entire space calculated by flexbox
img
width: 100%
opacity: .5
figure, img
margin: 0
padding: 0
Remove
flex-grow:1;
and they will be the same size!
I don't know it is what you want or not, just add the attribute on the class article:
justify-content: space-around;
or
justify-content: space-between;
The gap will disappear.
I need to put 3 columns inside a container. They are supposed to have the same width and evenly distributed. I use flex for that and it works fine.
In the end I need to insert a collection of "cards" in each column ... Because the number of cards can cause the columns to have a greater height than what can be displayed in the browser, the container (the parent of the columns) has overflow set to scroll. So when that happens you can still scroll down to look at the cards that are at the bottom of the column.
I have two problems that I'd like to fix:
1) As soon as I insert a card in the left column, that columns becomes larger than the other two. If I set the column to flex and set flex-grow to 0 on the card, it makes no difference. I am not sure why?
EDIT:
I fixed #1 by setting width: 33%; on .column.
===========================================================================
2) The left column is not drawn passed the bottom boundary of the browser, even though it contains cards causing the container to potentially overflow. What I want to do is be sure that the column "contains" the cards. How could I achieve that (using flex or not)?
I created a fidle and illustrated this problem with the figure below.
JSFIDDLE is here
1) As soon as I insert a card in the left column, that columns becomes
larger than the other two. If I set the column to flex and set
flex-grow to 0 on the card, it makes no difference. I am not sure why?
flex-grow does not define the width, it define how the available space should be distributed.
You could use flex-basis: 33.333%
2) The left column is not drawn passed the bottom boundary of the
browser, even though it contains cards causing the container to
potentially overflow. What I want to do is be sure that the column
"contains" the cards. How could I achieve that (using flex or not)?
Change the height: 100% on container to min-height: 100%
Stack snippet
html, body
{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.container
{
display: flex;
flex-direction: row;
border: 2px solid black;
overflow: scroll;
padding: 0;
margin: 0;
min-height: 100%; /* changed to 'min-height' */
width: 100%;
box-sizing: border-box;
}
.column
{
display: flex;
flex-direction: column;
flex: 1 1 auto;
background: grey;
margin: 5px;
}
.article
{
margin: 5px;
background: white;
height: 100px;
border: 1px solid orange;
}
<div class="container">
<div class="column">
<div class="article">article1</div>
<div class="article">article2</div>
<div class="article">article3</div>
<div class="article">article4</div>
<div class="article">article5</div>
<div class="article">article6</div>
<div class="article">article7</div>
</div>
<div class="column">col 2</div>
<div class="column">col 3</div>
</div>
To make the columns equal width, instead of flex: 1 1 auto, use flex: 1 1 0 (which is the same as flex: 1).
With flex-basis: auto the width of each column is based on its content, so equal width columns aren't guaranteed.
With flex-basis: 0, the width of all columns is an equal distribution of space in the container.
Here's a more complete explanation of flex-basis and the difference between auto and 0.
Make flex-grow expand items based on their original size
To make the divs respect their height: 100px, add flex-shrink: 0. Flex items have flex-shrink: 1, by default.
Here's a more complete explanation:
What are the differences between flex-basis and width?
To get the container to follow along, see the other answer to this question.
html,
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: row;
border: 2px solid black;
overflow: scroll;
padding: 0;
margin: 0;
min-height: 100vh;
box-sizing: border-box;
}
.column {
display: flex;
flex-direction: column;
background: grey;
margin: 5px;
flex: 1; /* adjustment */
}
.article {
margin: 5px;
background: white;
border: 1px solid orange;
flex: 0 0 100px; /* adjustment */
}
<div class="container">
<div class="column">
<div class="article">article1</div>
<div class="article">article2</div>
<div class="article">article3</div>
<div class="article">article4</div>
<div class="article">article5</div>
<div class="article">article6</div>
<div class="article">article7</div>
</div>
<div class="column">col 2</div>
<div class="column">col 3</div>
</div>
I'm trying to create a grid layout with the help of the flexbox.
What I'm doing is that I'm giving parent negative margin on left and right and then giving its child the same amount of padding on left and right for the gutter space.
I'm trying to make 5 column grid and when I use flex: 1 1 20% all the columns are not coming in the same row. The last get wrapped in the next row. This should not be the case as flex-basis is set to 20% and parent should accommodate all five columns in one row.
But when I'm trying to do this, the 4th grid item is getting wrapped on the next line.
Here is the working codepen for this issue.
Updated the codepen:
https://codepen.io/vikrantnegi007/pen/BZwGJQ
Thanks.
If I add bootstrap to to your codepen it works, which means you have some other issue we can't see in your original code.
Note though, based on your image's settings, your elements still might wrap
Still, instead of doing negative margin tricks, create a gutter, use justify-content: space-around and flex-basis.
Updated codepen
//testing css
.buisness-blocks {min-height: 250px;}
//main css
.buisness-blocks {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.block {
flex-basis: calc(20% - 10px);
outline: 1px solid;
}
}
Is box-sizing the CSS property you are looking for?
Giving the block's a box-sizing of border-box, they all come next to each other:
.block {
flex: 0 1 20%;
padding-right: 10px;
padding-left: 10px;
outline: 1px solid;
box-sizing: border-box;
}
https://codepen.io/anon/pen/vZeQjO
Just Try This hope its work
.buisness-blocks {min-height: 250px;}
.buisness-blocks {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
margin-right: 0px;
margin-left: 0px;
.block {
flex: 0 1 20%;
-webkit-flex: 10; /* Safari 6.1+ */
-ms-flex: 10; /* IE 10 */
flex: 2;
padding-right: 10px;
padding-left: 10px;
outline: 1px solid;
}
}
CLICK HERE for DEMO
If the negative margins isn't working with display flex, but you can try to use transform:
At the CSS style properties of the inner element add the translate that you wanna.
Example:
transform: translateY(15px);
P.S.: transform isn't portable to all browsers.