Flexbox: 4 items per row - html

I'm using a flex box to display 8 items that will dynamically resize with my page. How do I force it to split the items into two rows? (4 per row)?
Here is a relevant snip:
(Or if you prefer jsfiddle - http://jsfiddle.net/vivmaha/oq6prk1p/2/)
.parent-wrapper {
height: 100%;
width: 100%;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: -10px 0 0 -10px;
}
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 10px;
flex-grow: 1;
height: 100px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>

You've got flex-wrap: wrap on the container. That's good, because it overrides the default value, which is nowrap (source). This is the reason items don't wrap to form a grid in some cases.
In this case, the main problem is flex-grow: 1 on the flex items.
The flex-grow property doesn't actually size flex items. Its task is to distribute free space in the container (source). So no matter how small the screen size, each item will receive a proportional part of the free space on the line.
More specifically, there are eight flex items in your container. With flex-grow: 1, each one receives 1/8 of the free space on the line. Since there's no content in your items, they can shrink to zero width and will never wrap.
The solution is to define a width on the items. Try this:
.parent {
display: flex;
flex-wrap: wrap;
}
.child {
flex: 1 0 21%; /* explanation below */
margin: 5px;
height: 100px;
background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
With flex-grow: 1 defined in the flex shorthand, there's no need for flex-basis to be 25%, which would actually result in three items 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: 21%, there's plenty of space for the margins, but never enough space for a fifth item.

Add a width to the .child elements. I personally would use percentages on the margin-left if you want to have it always 4 per row.
DEMO
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 2%;
flex-grow: 1;
height: 100px;
width: calc(100% * (1/4) - 10px - 1px);
}

Here is another apporach.
You can accomplish it in this way too:
.parent{
display: flex;
flex-wrap: wrap;
}
.child{
width: 25%;
box-sizing: border-box;
}
Sample:
https://codepen.io/capynet/pen/WOPBBm
And a more complete sample:
https://codepen.io/capynet/pen/JyYaba

I would do it like this using negative margins and calc for the gutters:
.parent {
display: flex;
flex-wrap: wrap;
margin-top: -10px;
margin-left: -10px;
}
.child {
width: calc(25% - 10px);
margin-left: 10px;
margin-top: 10px;
}
Demo: https://jsfiddle.net/9j2rvom4/
Alternative CSS Grid Method:
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 10px;
grid-row-gap: 10px;
}
Demo: https://jsfiddle.net/jc2utfs3/

For more detail you can follow this Link
.parent{
display: flex;
flex-wrap: wrap;
}
.parent .child{
flex: 1 1 25%;
/*Start Run Code Snippet output CSS*/
padding: 5px;
box-sizing: border-box;
text-align: center;
border: 1px solid #000;
/*End Run Code Snippet output CSS*/
}
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
</div>

I believe this example is more barebones and easier to understand then #dowomenfart.
.child {
display: inline-block;
margin: 0 1em;
flex-grow: 1;
width: calc(25% - 2em);
}
This accomplishes the same width calculations while cutting straight to the meat. The math is way easier and em is the new standard due to its scalability and mobile-friendliness.

.parent-wrapper {
height: 100%;
width: 100%;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin-right: -10px;
margin-bottom: -10px;
}
.child {
background: blue;
height: 100px;
flex-grow: 1;
flex-shrink: 0;
flex-basis: calc(25% - 10px);
}
.child:nth-child(even) {
margin: 0 10px 10px 10px;
background-color: lime;
}
.child:nth-child(odd) {
background-color: orange;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
</style>
</head>
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
</html>
;)

Flex wrap + negative margin
Why flex vs. display: inline-block?
Flex gives more flexibility with elements sizing
Built-in white spacing collapsing (see 3 inline-block divs with exactly 33% width not fitting in parent)
Why negative margin?
Either you use SCSS or CSS-in-JS for the edge cases (i.e. first element in column), or you set a default margin and get rid of the outer margin later.
Implementation
https://codepen.io/zurfyx/pen/BaBWpja
<div class="outerContainer">
<div class="container">
<div class="elementContainer">
<div class="element">
</div>
</div>
...
</div>
</div>
:root {
--columns: 2;
--betweenColumns: 20px; /* This value is doubled when no margin collapsing */
}
.outerContainer {
overflow: hidden; /* Hide the negative margin */
}
.container {
background-color: grey;
display: flex;
flex-wrap: wrap;
margin: calc(-1 * var(--betweenColumns));
}
.elementContainer {
display: flex; /* To prevent margin collapsing */
width: calc(1/var(--columns) * 100% - 2 * var(--betweenColumns));
margin: var(--betweenColumns);
}
.element {
display: flex;
border: 1px solid red;
background-color: yellow;
width: 100%;
height: 42px;
}

you can try this
.parent-wrapper {
height:100%;
width:100%;
border: 1px solid black;
}
.parent {
display: grid;
font-size: 0;
grid-template-columns: 25% 25% 25% 25%;
}
.child {
background:blue;
flex-grow: 1;
height:100px;
margin: 10px;
margin-bottom: 0;
}
.child:last-child {
margin-bottom: 10px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
https://jsfiddle.net/samet19/gdntwLhb/

Here's another way without using calc().
// 4 PER ROW
// 100 divided by 4 is 25. Let's use 21% for width, and the remainder 4% for left & right margins...
.child {
margin: 0 2% 0 2%;
width: 21%;
}
// 3 PER ROW
// 100 divided by 3 is 33.3333... Let's use 30% for width, and remaining 3.3333% for sides (hint: 3.3333 / 2 = 1.66666)
.child {
margin: 0 1.66666% 0 1.66666%;
width: 30%;
}
// and so on!
That's all there is to it. You can get fancy with the dimensions to get a more aesthetic sizes but this is the idea.

Related

How to fix div child of parent center when "float:left"?

I tried to center child divs inside a parent div. Quantity of child div is dynamic and I make "float: left". But group of child divs can't center inside a parent div.
Parent div static width: 800px;
Child divs static width: 360px; height: 320px.
Here my code:
* {
box-sizing: border-box;
}
.parent {
width: 800px;
display: flex;
justify-content: center;
background-color: #f8f9fb;
}
.child {
width: 360px;
margin: 7px;
min-width: 360px;
height: 320px;
float: left;
background-color: #FFFF;
border: 1px solid;
}
<div class="parent">
<div class="content">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
Some way I references but not in my case:
- http://jsfiddle.net/h9H8w/12/
- https://dev.to/stel/a-little-trick-to-left-align-items-in-last-row-with-flexbox-230l
- https://codepen.io/anon/pen/JbpPKa
My results like that:
- https://imgur.com/TX9I4vq
- https://imgur.com/NiRaHgj
Thanks for reading and sorry my bad english.
========================================================
From the help of #kukkuz. I changed my code:
* {
box-sizing: border-box;
}
.parent {
max-width: 800px;
display: grid;
justify-content: center;
background-color: #f8f9fb;
grid-template-columns: repeat( auto-fit, 360px);
grid-gap: 7px;
}
.child {
width: 360px;
/*margin: 7px;*/
min-width: 360px;
height: 320px;
/* float: left;*/
background-color: #FFFF;
border: 1px solid;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
Is this what u want,
Basically I removed the float:left and the content div
justify-content: center; will handle the centering of the boxes,
Uncomment flex-wrap:wrap; to wrap the children on to the next line
Know that, making a div display:flex, will make its children flex-items, which was not happening in your case
* {
box-sizing: border-box;
}
.parent {
width: 800px;
display: flex;
justify-content: center;
background-color: #f8f9fb;
/*flex-wrap:wrap;*/
}
.child {
width: 36px;
margin: 7px;
min-width: 36px;
height: 32px;
background-color: #FFFF;
border: 1px solid;
}
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
</div>

Empty space for one columns width with flexbox

I have a parent div and two divs inside. I want to keep specific sizes (columns) for those child divs. Is this possible in flexbox? I'm strugling with this.
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
First child should have width of 1 column, second child width of 2 columns. On right side I want to have empty space in width of 1 column (so parent div should behave like it has 4 columns).
Here's a method using flex-basis to set flex items to specific percentage widths.
In this example, the two flex items can neither shrink nor grow. Splitting 100% width into four columns, each column needs to be 25% of the parent width. The first item is 25% and the second is 50% (two columns wide), leaving 25% space on the right.
.parent {
display: flex;
min-height: 10em;
border: 1px solid #CCC;
}
.child {
outline: 1px solid black;
background-color: lightgray;
}
.child:nth-child(1) {
flex: 0 0 25%
}
.child:nth-child(2) {
flex: 0 0 50%;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
EDIT
I notice you'd like some space between each column. One way is to add some right margin percentage to flex items and subtract that percentage from each item's flex-basis.
.parent {
display: flex;
min-height: 10em;
border: 1px solid #CCC;
}
.child {
outline: 1px solid black;
background-color: lightgray;
margin-right: 3%;
}
.child:nth-child(1) {
flex: 0 0 22%;
}
.child:nth-child(2) {
flex: 0 0 47%;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
If you'd rather that the space between columns not be a percentage, you can use calc() to calculate the appropriate flex-basis. However, note that this is not supported in IE or Edge at the time of this post.
IE & Edge are reported to not support calc inside a 'flex'. (Not tested on older versions)
This example does not work: flex: 1 1 calc(50% - 20px);
caniuse.com
.parent {
display: flex;
min-height: 10em;
border: 1px solid #CCC;
}
.child {
outline: 1px solid black;
background-color: lightgray;
margin-right: 0.5em;
}
.child:nth-child(1) {
flex: 0 0 calc(25% - 0.5em);
}
.child:nth-child(2) {
flex: 0 0 calc(50% - 0.5em);
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
You can achieve this using flexbox by using a pseudo element that occupies the fourth column:
add flex: 1 to the first child and the pseudo element,
add flex: 2 to the second child.
See demo below:
.parent {
display: flex;
height: 100px;
border: 1px solid #ddd;
}
.child {
border: 1px solid cadetblue;
background: lightblue;
flex: 1;
}
.child + .child {
flex: 2;
}
.parent:after {
content: '';
flex: 1;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
And the easier solution using CSS Grid layout - establish a 4-column layout and span the second child element over two columns:
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
height: 100px;
border: 1px solid #ddd;
}
.child {
border: 1px solid cadetblue;
background: lightblue;
}
.child + .child {
grid-column: span 2;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
Nobody seems to have suggested you could just set the width of the parent:
.parent {
width: 75%;
display: flex;
}
.child {
flex: 150;
height: 2rem;
border: 1px solid #000;
}
.child:first-child {
flex: 75;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
EDIT:
And to add, you want your second child to be twice as big as your first, so give your second child a flex value of something that's twice as big as your first - I used 1 and 2, but you could've used flex: 75 and flex: 150 to achieve the same effect.

Flex-wrap property not responsive when parent has a set width

In the example below, when I set a width for a wrapper, the parent flex container can no longer use the flex-wrap property. The top two boxes won't wrap, but the bottom ones will.
<div class="wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
.wrapper {
width: 700px;
margin: 0 auto;
border: solid cadetblue 5px;
}
.parent {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.child {
height: 250px;
min-width: 250px;
max-width: 300px;
flex: 1;
background: mistyrose;
border: solid goldenrod 2px;
margin: 30px;
}
The 'issue' you raise is by design; you're specifying a width for the parent that is wide enough for your children to be wholly contained within (a 700px container for two 300px children). flex-wrap only causes elements to overflow when there's not enough space for the container to hold them. In your example, there is.
To force an overflow responsively, you could either specify a narrow width on the parent(which will cause an overflow for all viewports):
.wrapper {
width: 400px;
margin: 0 auto;
border: solid cadetblue 5px;
}
.parent {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.child {
height: 250px;
min-width: 250px;
max-width: 300px;
flex: 1;
background: mistyrose;
border: solid goldenrod 2px;
margin: 30px;
}
<div class="wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
Or use max-width instead(which will only overflow on narrow viewports):
.wrapper {
max-width: 700px;
margin: 0 auto;
border: solid cadetblue 5px;
}
.parent {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.child {
height: 250px;
min-width: 250px;
max-width: 300px;
flex: 1;
background: mistyrose;
border: solid goldenrod 2px;
margin: 30px;
}
<div class="wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
</div>

Keep space / padding between Divs

How would I be able to keep the space between my inlined div elements without counting the space as 'pixels'?
For example, currently i'm using margin-right (as my padding between my elements) but is eventually counting that as pixels (the result shows off ugly, see JsFiddle, div element gets pushed down).
#parent .child
{
position: relative;
display: inline-block;
height: 100%;
width: 16.5%;
background-color: green;
margin-right: 15px;
}
JsFiddle
Basically, I just like to have the first item floaten left and the last item floaten right. Now I know many of you guys are thinking, why not just use the feature 'justify'? I've tried using it, but it isn't a really good option since the amount of elements can be everything (10, 5, 8, etc).
Help would be appericiated!
EDIT: This basically is the feature i'd like to achieve but for multiple elements (instead of having only 1 row, there could be 2-16 rows.
You can use text-align: justify. It won't justify the last line, but you can force a new line with a pseudo-element:
#parent {
text-align: justify;
background-color: red;
}
#parent:after {
content: '';
display: inline-block;
width: 100%;
}
#parent .child {
display: inline-block;
height: 100px;
width: 16.5%;
background-color: green;
margin-right: 15px;
margin-bottom: 10px;
}
<div id="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
If I understand it properly, you want to set an internal margin between the children, but not between the edge children and the parent. Something like
.child { margin-right: 15px; }
.child:last-of-line { margin-right: 0; }
Currently there is no way to do that, but you can add an additional wrapper with a negative margin:
#inner-wrapper {
margin-right: -15px;
margin-bottom: -10px;
}
.child {
margin-right: 15px;
margin-bottom: 10px;
}
#parent {
background-color: red;
overflow: hidden;
}
#inner-wrapper {
margin-right: -15px;
margin-bottom: -10px;
}
.child {
vertical-align: top;
display: inline-block;
height: 210px;
width: 16.5%;
background-color: green;
margin-right: 15px;
margin-bottom: 10px;
}
<div id="parent">
<div id="inner-wrapper">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>

CSS Make last child to dynamically take width which left in parent

In my case childs number is returned from server side. In case there are less than 6 childs I need to add dummy child which would take left place of parent.
For example :
1 situation with two childs
2 situation with three childs
fiddle
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="big-child"></div>
</div>
#container{
width: 100%;
height: 200px;
background-color: gray;
}
#container > div {
float: left;
background-color: black;
width: 100px;
height: 100px;
margin-right: 20px;
}
.big-child {
width: 59%!important;
margin-right: 0px!important;
}
How could I achieve this with only CSS and withoud dinamically changing child width with javascript?
UPDATE
Found good website which generates CSS code depending on your boxes needs.
On modern browser you could use flexbox
http://codepen.io/anon/pen/yyMgQL
CSS:
#container {
display: -ms-flexbox; /* IE 10 syntax */
display: flex;
width: 100%;
height: 200px;
background-color: gray;
}
#container > div {
background-color: black;
width: 100px;
height: 100px;
margin-right: 20px;
}
#container > div.big-child {
-ms-flex-grow: 1; /* IE 10 syntax */
flex-grow: 1;
margin-right: 0;
}
Further info:
- http://css-tricks.com/snippets/css/a-guide-to-flexbox/
- http://css-tricks.com/old-flexbox-and-new-flexbox/
Browser support: http://caniuse.com/#feat=flexbox
(note that IE10 is supported but it implements an older syntax)
If you want to use floats, you can use overflow:hidden; on the last child to force it to occupy the remaining space.
Alternative solutions could be to use flexbox (depending on your required browser support) or CSS tables.
#container {
width: 100%;
height: 200px;
background-color: gray;
}
#container > div {
box-sizing: border-box;
margin-right: 0;
height: 100px;
}
#container > div:not(:last-child) {
margin-right: 10px;
}
.child {
float: left;
background-color: black;
width: 100px;
}
.big-child {
overflow: hidden;
background-color: black;
margin: 0 20px;
}
<h4>Three Blocks</h4>
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="big-child"></div>
</div>
<h4>Two Blocks</h4>
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="big-child"></div>
</div>