I'm struggling with the wrapping option of the css flexbox in combination with margins between the items.
What I'm trying to archieve is: Have a flexcontainer with wrapping enabled and a number of items with variable with and minimum width. Between these items I want to have a small gap (margin) but I don't want a margin between the item and the container on the left or right side.
Right now I'm using the first-child and last-child pseudo class but this approach doesn't work unfortunatly when the container wraps the content. See JsFiddle for a minimalistic demo.
HTML
<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>
CSS
.container {
display: flex;
flex-wrap: wrap;
border: 1px solid red;
}
.item {
min-width: 100px;
flex: 1;
border: 1px solid black;
margin-left: 20px;
margin-right: 20px;
}
.item:first-child {
margin-left: 0px;
}
.item:last-child {
margin-right: 0px;
}
Any suggestions?
flexbox has some specific properties, so in your case this is what needs to be fixed:
instead of min-width use flex-basis
use justify-content: space-between
to apply margin on items there's a special hack (check out the
example -to fix border coherency apply a wrapper);
.container-bg {
width:100%;
border: 1px solid green;
overflow:hidden;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
/* border: 1px solid red;*/
margin: 0 -20px;
}
.item {
/*min-width: 100px;*/
flex: 1 0 100px;/*if you want to set 100px as min-width you'll have to set flex-shrink to 0*/
border: 1px solid black;
margin: 0 20px;
}
/*.item:first-child {
margin-left: 0px;
}
.item:last-child {
margin-right: 0px;
}*/
<p>resize the window for wrapping</p>
<div class="container-bg"><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></div>
EDIT :
set flex-shrink to 0 is don't want to go below a certain width..
If you add another wrapper around your items, you can use this dirty hack: https://jsfiddle.net/xw5uo2j1/13/
You set your main container to be 100% of the width, then your "sub" container to be 100% plus the amount of space between you're going to add. Then add the same amount of margin-right to the items.
.maincontainer {
width:100%;
border: 1px solid red;
}
.container {
display: flex;
flex-flow: row wrap;
justify-content:space-between;
align-content:space-between;
width:calc(100% + 5px);
}
.item {
min-width: 100px;
flex: 1;
border: 1px solid black;
margin-right:5px;
}
<p>resize the window for wrapping</p>
<div class="maincontainer">
<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>
</div>
UPDATED, with more than 5 items
Use calc and jusify-content: space-between;
* {
box-sizing: border-box;
margin: 0;
}
.container {
border: thin solid red;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
margin: 0 -10px;
}
.item {
border: thin solid black;
-webkit-flex: 1 1 calc(20% - 20px);
flex: 1 1 calc(20% - 20px);
margin: 0 10px;
padding: 20px;
position: relative;
}
<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>
Related
I'm trying to use flexbox in order to create two columns of three row for the Products. I looked to other similar problem on StackOverflow but the answers given didn't work for me. Could you help me please ?
Here the HTML code:
Informations {
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid blue;
width: 100%;
display: flex;
justify-content: space-between;
}
.Information {
border: 1px solid blue;
margin: 0.5em;
padding: 0.5em;
}
Game {
list-style-type: none;
border: 1px solid red;
width: 100%;
display: flex;
}
.ProductContainer {
display: flex;
flex-flow: column wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
}
.UpgradeContainer {
border: 1px solid black;
width: 10%;
}
.Upgrade {
display: flex;
flex-flow: column wrap;
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
}
<!DOCTYPE world>
<html>
<head>
<title> World </title>
</head>
<body>
<Informations>
<div class="Information">Your World:</div>
<div class="Information">Your Money:</div>
<div class="Information">Your ID:</div>
</Informations>
<Game>
<div class="UpgradeContainer">
<div class="Upgrade">Unlocks</div>
<div class="Upgrade">Cash</div>
<div class="Upgrade">Angels</div>
<div class="Upgrade">Managers</div>
<div class="Upgrade">Investors</div>
</div>
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
</Game>
</body>
</html>
I basically want to have to the left my upgrades (Cash, angels...) and in the middle and right two column of three row of products.
Here is my code pen to see: https://codepen.io/Tameiki/pen/oNXpNVe
You can use the flex-wrap property together with setting the flex-basis on the child elements:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
Notice how I removed the flex-direction:column property: the child elements will attempt to fit in a single row, overflowing the container if necessary.
.ProductContainer{
display: flex;
/*flex-flow: wrap;*/
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
/*flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
flex-wrap is what makes them start a new line instead of overflowing:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
/*flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
But how do we get only two of them per row? By telling each of the child elements to be half the row's width:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
flex-basis: 50%; /*calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
Unfortunately, flex-basis applies to the inner width of an element - including paddings, but excluding margins and borders. Usually, Flexbox tries to shrink child elements to fit the row if possible, but flex-wrap disables this, so we will have to adjust manually. That gets you to the code at the top.
I have something like this :
.wrapper {
display: flex;
width: 300px;
}
.content {
flex: auto;
}
.row {
display: flex;
flex-flow: row wrap;
}
.col {
width: 25%;
padding: 5px;
border: 1px solid black;
box-sizing: border-box;
}
<div class='wrapper'>
<div class='content'>Content</div>
<div class='row'>
<div class='col'>aa</div>
<div class='col'>aaaa</div>
<div class='col'>aaaaaa</div>
<div class='col'>aaaaaaaa</div>
</div>
</div>
I can't understand how :
The width of the .row element is calculated
The width of the .col elements are calculated
Why some content overflows the box and some don't
What I want is a grid system that gets its size relative to the largest child, so that each content fits in its .col cell.
I saw that I could do that with display: grid and grid-template-columns: 1fr 1fr 1fr 1fr, but then how do you make it responsive and how well is it supported ?
To answer your 3 first questions, you simly need to remove the width:25% to have the following:
.wrapper {
display: flex;
width: 300px;
}
.content {
flex: auto;
}
.row {
display: flex;
flex-flow: row wrap;
}
.col {
padding: 5px;
border: 1px solid black;
box-sizing: border-box;
}
<div class='wrapper'>
<div class='content'>Content</div>
<div class='row'>
<div class='col'>aa</div>
<div class='col'>aaaa</div>
<div class='col'>aaaaaa</div>
<div class='col'>aaaaaaaa</div>
</div>
</div>
We didn't define any width, so each col will fit its content and the row will have the width equal to the sum of all the col.
Now since we have the width of the row defined based on the content, it won't change and it will get used as a reference for the percentage. Using 25% for the col means that each one will get 25% of the previously defined width and we will logically have some overflow since the content inside each col isn't the same.
.wrapper {
display: flex;
width: 300px;
}
.content {
flex: auto;
}
.row {
display: flex;
flex-flow: row wrap;
}
.col {
padding: 5px;
border: 1px solid black;
box-sizing: border-box;
}
.width .col {
width:25%;
}
<div class='wrapper'>
<div class='content'>before width</div>
<div class='row'>
<div class='col'>aa</div>
<div class='col'>aaaa</div>
<div class='col'>aaaaaa</div>
<div class='col'>aaaaaaaa</div>
</div>
</div>
<div class='wrapper'>
<div class='content'>after width</div>
<div class='row width'>
<div class='col'>aa</div>
<div class='col'>aaaa</div>
<div class='col'>aaaaaa</div>
<div class='col'>aaaaaaaa</div>
</div>
</div>
To obtain what you want, I think the 1fr of CSS grid is the way to go (like you already noticed). Actually CSS grid is well supported. You will simply have issues with IE and you can follow this link to see the known bugs: https://caniuse.com/#feat=css-grid
In order to make it responsive you may consider media query to switch to a column layout on small screens:
.wrapper {
display: flex;
width: 300px;
}
.row {
display: grid;
grid-auto-columns:1fr;
grid-auto-flow:column;
}
.col {
padding: 5px;
border: 1px solid black;
box-sizing: border-box;
}
#media all and (max-width:500px) {
.row {
grid-auto-flow:row;
}
}
<div class='wrapper'>
<div class='content'>Content</div>
<div class='row'>
<div class='col'>aa</div>
<div class='col'>aaaa</div>
<div class='col'>aaaaaa</div>
<div class='col'>aaaaaaaa</div>
</div>
</div>
I've got four div's in a flexbox grid. I want them to wrap two at a time, like this:
+-----------------------+
| 1 | 2 | 3 | 4 |
+-----------------------+
+-----------+
| 1 | 2 |
+-----------+ THIS IS WHAT I WANT
| 3 | 4 |
+-----------+
+-----+
| 1 |
+-----+
| 2 |
+-----+
| 3 |
+-----+
| 4 |
+-----+
Now, this seems easy enough, just nest them inside new flex containers and apply flex-wrap, and give the cells some min-widths. However, this has the side-effect of making the middle view look like this:
+-----------+
| 1 | 3 |
+-----------+ NOT WHAT I WANT
| 2 | 4 |
+-----------+
Apparently, flexbox wants to first wrap the inner div's instead of considering them rows. In order to keep all of the other wrapping working, setting flex-basis (to e.g. 100%) for the nested div's is not an option. In order to keep everything dynamic (for instance adding a third cell to one of the rows), setting %-widths on the cells is not an option. And in order to avoid hard breakpoints and base wrapping on (dynamic) content width, I'd really like to avoid media queries.
Can this be achieved with flexbox and without media queries?
JSFiddle
div {
box-sizing: border-box;
margin: 2px;
}
.grid {
display: flex;
flex-flow: row wrap;
border: 2px solid blue;
flex: 1;
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
<div class="grid">
<div class="grid">
<div class="cell">1</div>
<div class="cell">2</div>
</div>
<div class="grid">
<div class="cell">3</div>
<div class="cell">4</div>
</div>
</div>
EDIT: I know I can make the inner .grid not wrap at all, but what I really want is for all the cells to wrap below each other if space is super tight. (As in the first illustration.)
You need to tell the children-elements of .grid .grid to flow in a row:
div {
box-sizing: border-box;
margin: 2px;
}
.grid {
display: flex;
flex-flow: row wrap;
border: 2px solid blue;
flex: 1;
}
.grid .grid {
flex-flow: row; /* this is your fix */
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
<div class="grid">
<div class="grid">
<div class="cell">1</div>
<div class="cell">2</div>
</div>
<div class="grid">
<div class="cell">3</div>
<div class="cell">4</div>
</div>
</div>
Note, there is no specific Flexbox property that replace a media query, and no need either as media queries is perfect for this, better than any other available method or property.
The trick here is to make the inner grid's to wrap before the cell's does. For that to happen they also need a minimum width, which is wider than the sum of the 2 cell's.
The downside with that extra min-width is it will also affect the cell's width on narrower screens
Fiddle demo 1
Stack snippet
div {
box-sizing: border-box;
margin: 2px;
}
.grid-outer {
display: flex;
flex-wrap: wrap;
border: 2px solid blue;
}
.grid-inner {
flex: 1;
display: inline-flex;
flex-wrap: wrap;
border: 2px solid blue;
min-width: 210px;
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
<div class="grid-outer">
<div class="grid-inner">
<div class="cell">1</div>
<div class="cell">2</div>
</div>
<div class="grid-inner">
<div class="cell">3</div>
<div class="cell">4</div>
</div>
</div>
An option is to drop the Flexbox properties on the outer grid and set the inner grid's to inline-flex and let the cells grow with their content.
The downside with this is that the cell's won't fill their parents width
Fiddle demo 2
Stack snippet
div {
box-sizing: border-box;
margin: 2px;
}
.grid-outer {
display: inline-block;
}
.grid-inner {
display: inline-flex;
flex-wrap: wrap;
border: 2px solid blue;
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
<div class="grid-outer">
<div class="grid-inner">
<div class="cell">1</div>
<div class="cell">2</div>
</div>
<div class="grid-inner">
<div class="cell">3</div>
<div class="cell">4</div>
</div>
</div>
The absolute best solution here is a combination of Flexbox and a media query, where one use the query to alter the outer grid's flex direction to column...
Fiddle demo
Stack snippet
div {
box-sizing: border-box;
margin: 2px;
}
.grid-outer {
display: flex;
border: 2px solid blue;
}
.grid-inner {
flex: 1;
display: flex;
border: 2px solid blue;
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
#media (max-width: 600px) {
.grid-outer {
flex-direction: column;
}
}
<div class="grid-outer">
<div class="grid-inner">
<div class="cell">1</div>
<div class="cell">2</div>
</div>
<div class="grid-inner">
<div class="cell">3</div>
<div class="cell">4</div>
</div>
</div>
...or drop the inner grid's all together and change the cell's flex basis
Fiddle demo
Stack snippet
div {
box-sizing: border-box;
margin: 2px;
}
.grid-outer {
display: flex;
flex-wrap: wrap;
border: 2px solid blue;
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
#media (max-width: 600px) {
.cell {
flex-basis: calc(50% - 4px);
}
}
<div class="grid-outer">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
</div>
Having different definitions for the grids does the job. I redefined them as outer and inner grid.
EDIT: Added wrap for .grid-inner to cover width < 200px
div {
box-sizing: border-box;
margin: 2px;
}
.grid-outer {
display: flex;
flex-flow: row wrap;
border: 2px solid blue;
flex: 1;
width: 230px; /* for demo purposes */
}
.grid-inner {
display: flex;
border: 2px solid green;
flex-wrap: wrap;
}
.cell {
flex: 1;
min-width: 100px;
border: 2px solid red;
background: white;
height: 100px;
}
<div class="grid-outer">
<div class="grid-inner">
<div class="cell">1</div>
<div class="cell">2</div>
</div>
<div class="grid-inner">
<div class="cell">3</div>
<div class="cell">4</div>
</div>
</div>
I have a page that is 50/50 wide. The left half has a row with six divs.
Criteria:
6 squares must always remain square.
First 5 squares should have margin/padding to right for separation.
All six squares must stay on same single row. If I can get that to work i can make the needed adjustments for responsiveness in smaller viewports.
Cross browser compatible for newest version of ie, chrome, and firefox.
My codepen: https://codepen.io/johnsontroye/pen/zzNVBr
Image:
<body>
<div class="container">
<div class="column" style="margin-right: 20px">
<div class="flex-container">
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L1
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L2
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L3
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L4
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L5
</div>
</div>
</div>
<div class="flex-item">
<div class="flex-item-inner">
<div class="flex-item-inner-content">
L6
</div>
</div>
</div>
</div>
</div>
<div class="column" style="margin-left: 20px; border: 1px black solid; height: 500px">
Other stuff
<div>
</body>
.container {
display: flex;
flex-direction: row;
padding: 25px;
border: 2px red solid;
}
.column {
width: 100%;
height: 100%;
float: left;
}
.flex-container {
padding: 0;
font-size: 0;
border: 1px solid black;
box-sizing: border-box;
}
.flex-item {
position: relative;
display: inline-block;
height: 0;
width: 100%;
padding-top: 100%;
border: 1px black solid;
font-size: 20px;
color: black;
font-weight: bold;
text-align: center;
box-sizing: border-box;
}
#media (min-width: 480px) {
.flex-item {
width: 33.3333%;
padding-top: 33.3333%;
}
}
#media (min-width: 768px) {
.flex-item {
width: 16.6666%;
padding-top: 16.6666%;
}
}
.flex-item-inner {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin-right: 25px;
background: white;
border: 1px solid red;
box-sizing: border-box;
}
.flex-item-inner-content {
border: 1px solid orange;
}
.flex-item:last-child .flex-item-inner {
margin-right: 0;
color: green;
}
The main trick here is to make the div a square.
Normally one set a width, the height to 0 and a padding that equals to the width
.square {
height: 0;
width: 33%;
padding-bottom: 33%;
background: lightgray;
}
<div class="square">
<div>
Content
</div>
</div>
Now, when we add display: flex, we can't use padding with percent (Firefox bug) and we can't use height with percent since we used height: 0.
To overcome these issues when can use viewport units vw instead, and with that we can also use height instead of padding to keep it squared.
So instead of setting a width like this, calc((100% / 6) - 10px);, to spread 6 items equally with a gutter about 10px wide, we use viewport units like this calc(( (50vw - 65px) / 6) - 10px);
The 50vw is half the browser width, the 65px is the sum of the container's left/right padding, 50px, plus the 15px gutter between the columns.
This also allows us to skip the extra flex-item-inner element, skip using position: absolute on the content element, and, as we didn't use percent for the height on the flex-item, we can do like this to center the content
.flex-item-content {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
And the end result is this
Fiddle demo
Stack snippet
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 25px;
border: 2px red solid;
}
.column {
flex-basis: calc(50% - 15px);
}
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.flex-item {
position: relative;
flex-basis: calc(( (50vw - 65px) / 6) - 10px);
height: calc(( (50vw - 65px) / 6) - 10px);
background: white;
border: 1px solid red;
overflow: hidden;
}
.flex-item-content {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.flex-item:last-child .flex-item-content {
color: green;
}
.column .other {
padding: 15px;
border: 1px solid black;
padding-bottom: 35px;
}
.column.left .other {
margin-top: 10px;
}
.column.right .other:nth-child(n+2) {
margin-top: 10px;
}
#media (max-width: 768px) {
.flex-item {
flex-basis: calc(( (50vw - 65px) / 3) - 10px);
height: calc(( (50vw - 65px) / 3) - 10px);
}
.flex-item:nth-child(n+4) {
margin-top: 12px;
}
}
#media (max-width: 480px) {
.flex-item {
flex-basis: calc(( (50vw - 65px) / 2) - 10px);
height: calc(( (50vw - 65px) / 2) - 10px);
}
.flex-item:nth-child(n+3) {
margin-top: 15px;
}
}
<div class="container">
<div class="column left">
<div class="flex-container">
<div class="flex-item">
<div class="flex-item-content">
L1
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L2
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L3
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L4
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L5<br>L5
</div>
</div>
<div class="flex-item">
<div class="flex-item-content">
L6
</div>
</div>
</div>
<div class="other">
Other stuff - left
</div>
</div>
<div class="column right">
<div class="other">
Other stuff - right
</div>
<div class="other">
Other stuff - right
</div>
</div>
</div>
This is doable with some fairly simple code, as long as the parent column's width is consistent at 50%-ish, and that the space between squares don't have to be strictly equal to a certain value. The vw (viewport width percentage) unit allows for a consistent size to be applied to both width and height of an element.
Here is an example that I boiled down to the fewest elements, and some notes help to move it in to your codebase.
Experiment with .flex-item's height and flex-basis (third value of flex) to get a size you like.
No padding or margin values are needed because justify-content: space-between; helpfully calculates that for us.
Using a line-height equal to the height of .flex-item would allow for an inner element with display: inline-block; and vertical-align: middle; to be centred.
.column {
width: 48vw;
height: 48vw;
padding: 1vw;
border: 1px solid #ccc;
}
.flex-container {
display: flex;
flex-flow: row;
justify-content: space-between;
}
.flex-item {
height: 6vw;
line-height: 6vw;
text-align: center;
border: 1px solid #ccc;
flex: 0 0 6vw;
}
<div class="column">
<div class="flex-container">
<div class="flex-item">
L1
</div>
<div class="flex-item">
L2
</div>
<div class="flex-item">
L3
</div>
<div class="flex-item">
L4
</div>
<div class="flex-item">
L5
</div>
<div class="flex-item">
L6
</div>
</div>
</div>
Only in the latest browsers? CSS Grid to the rescue! It's got great support in the latest versions. You may need some vendor prefixes still; check on CanIUse for the details.
Here it is as a fork: https://codepen.io/jackmakesthings/pen/MoJNNV
.container {
display: flex;
flex-direction: row;
padding: 25px;
border: 2px red solid;
}
.column {
width: 100%;
height: 100%;
float: left;
}
.grid-row {
display: grid;
grid-gap: 10px; /* set this to whatever space you need between boxes */
grid-template-columns: repeat(6, 1fr); /* grid autosizes 6 columns */
}
.row-item {
grid-column: 1 / 7; /* to span the whole row */
border: 1px solid;
padding: 10px;
}
.grid-item {
position: relative;
border: 1px solid;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
/* This is a nifty trick for getting those fixed aspect ratio boxes. */
.grid-item:before {
content: '';
float: left;
width: 0;
height: 0;
padding-bottom: 100%;
}
.grid-item:after {
display: table;
clear: both;
}
/* Responsive grid changes? Sure! */
#media (max-width: 1000px) {
/* We just have to change the grid template: */
.grid-row {
grid-template-columns: repeat(3, 1fr);
}
/* Unexpected thing I ran into - you also have to change this, or the grid stays big enough to accommodate the old 6-column-sized row-item. Makes sense, but vexed me for a minute! */
.row-item {
grid-column: 1 / 4;
}
}
<div class="container">
<div class="column" style="margin-right: 20px">
<div class="grid-row">
<div class="grid-item">L1</div>
<div class="grid-item">L2</div>
<div class="grid-item">L3</div>
<div class="grid-item">L4</div>
<div class="grid-item">L5</div>
<div class="grid-item">L6</div>
<div class="row-item">some other thing</div>
<div class="row-item">and another</div>
</div>
</div>
<div class="column" style="margin-left: 20px; border: 1px black solid; height: 500px">
Other stuff
<div>
How do I make a flex parent with a nowrap flex-wrap expand to fit its content even if that means overflowing whatever is wrapping the parent?
Basically, the content has a min-width, I want the flex parent not to shrink more than the space all the flex items need.
Here is a JSFiddle https://jsfiddle.net/lazamar/odat477r/
.wrapper {
background-color: yellowgreen;
display: block;
padding: 10px;
max-width: 180px;
}
.parent {
display: flex;
flex-flow: row nowrap;
background-color: yellow;
}
.child {
display: block;
background-color: orange;
margin: 10px;
min-width: 50px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
</div>
</div>
The answer is what t1m0n said. Use display: inline-flex instead of display: flex for the parent.
.wrapper {
background-color: yellowgreen;
display: block;
padding: 10px;
max-width: 180px;
}
.parent {
display: inline-flex; /* -- only change --*/
flex-flow: row nowrap;
background-color: yellow;
}
.child {
display: block;
background-color: orange;
margin: 10px;
min-width: 50px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
</div>
</div>
Using display: inline-flex instead of display: flex is your best bet.
If, for any reason, that's not an option, use CSS positioning properties.
.wrapper {
background-color: yellowgreen;
display: block;
padding: 10px;
max-width: 180px;
position: relative; /* new; set bounding box for flex container */
min-height: 40px; /* new */
}
.parent {
display: flex;
flex-flow: row nowrap;
background-color: yellow;
position: absolute; /* new; remove flex container from document flow */
}
.child {
/* display: block; <-- not necessary */
background-color: orange;
margin: 10px;
min-width: 50px;
}
<div class="wrapper">
<div class="parent">
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
<div class="child">Content</div>
</div>
</div>