I have a row of items of arbitrary width. They are centered within the container (note white space on the left and right sides of the red container):
Sometimes the container gets smaller than the width of all items:
When this happens, I want the items in the end to wrap to the next row like this:
It is very imporant for me that each row's content must be left-aligned, but the grid as a whole must be centered:
Initially, I tried implementing it with FlexBox. After a lot of frustration and hair pulling, I've learned that this is impossible witn FlexBox: https://stackoverflow.com/a/32811002/901944
Another answer on the same page suggests using CSS grid instead of flexbox.
CSS grid produces a slightly different result, but that also suits me:
Here's the code that makes it work:
.red-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
justify-content: center;
}
This code contains a lot of keywords that I don't understand: grid-template-columns
, repeat
, auto-fit
, minmax
and max-content
. I tried reading up on them and failed. None of guides and API docs explicitly explain how this particualr combination works. MDN docs are way too short and cryptic.
What I specifically struggle with is this 210px
magic number. Why is it necessary? (Erm, I know it's necessary because how the spec is designed, but this does not help me understand.)
The sizes of items in my grid are arbitrary, so I can't use a fixed value. Also, setting this fixed value makes the result slightly off: small items grow and large items overflow the container.
What I essentially want is:
grid-template-columns: repeat(auto-fit, minmax(min-content, max-content));
but that rule is recognized by browsers as faulty.
I've stumbled upon this answer that explains that using both min-content
and max-content
together is forbidden by the spec in this context. The answer's suggested solution is... to use Flexbox!
The loop has closed. I'm back to where I started, expect that I'm now lacking hair on my head for another round.
How to do I center my grid while left-aligning each row's content, with items having arbitrary widths?
Here's a boilerplate to fiddle with for your convenience: https://jsbin.com/vuguhoj/edit?html,css,output
The container can be resized by dragging it by the bottom-right corner.
PS No display: inline
and float: left
please.
.page {
border: 1px solid black;
overflow: hidden;
resize: horizontal;
max-width: 500px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(max-content, 50px));
justify-content: center;
}
.item {
border: 1px solid black;
margin: 1px;
}
<div class="page">
<div class="grid">
<div class="item">
Foofoofoo
</div>
<div class="item">
Bar
</div>
<div class="item">
BazBaz
</div>
<div class="item">
QuuxQuuxQuux
</div>
</div>
</div>
One of the easiest ways of centering the content of grid items is using Flexbox. Set the display to "grid" for the grid container, and "flex" for grid items. Then, add the align-items and justify-content properties, both with the "center" value, to grid items.
To center the items within a column, we use align-items and justify-items instead of the align-content and justify-content in our previous example. Using the item properties, we can align our items just like we did with our columns.
To just center the text inside an element, use text-align: center; This text is centered.
CSS grid approach-
root answer - joe82
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(179px, max-content));
grid-gap: 10px;
justify-content: center;
background: #999;
overflow: hidden;
padding: 10px;
}
.background {
width: 179px;
height: 64px;
background: #99d9ea;
}
.background .child {
border: 2px solid #000;
}
.background:nth-child(1) .child {
width: 110px;
height: 50px;
}
.background:nth-child(2) .child {
width: 120px;
height: 60px;
}
.background:nth-child(3) .child {
width: 50px;
height: 55px;
}
.background:nth-child(4) .child {
width: 175px;
height: 40px;
}
<div class="container">
<div class="background"><div class="child"></div></div>
<div class="background"><div class="child"></div></div>
<div class="background"><div class="child"></div></div>
<div class="background"><div class="child"></div></div>
</div>
Newbie here!
I admit that the above one isn't the output you desired, but it is my best attempt towards it, with the use of CSS grids. Here, you can understand that if we want to make it responsive then a minimum width is required after which, the column(content) will get carried to the next line, and that width is defined here(grid-template-columns: repeat(auto-fit, minmax(204px, max-content));
) 204px. But because of it each column will take that much width at least, that's why I represented the actual dimension of a column with blue background and the actual content within the border.I just post it for your acknowledgment and approach so that you can get closer to the actual answer.
By the way, Flex Approach-
root idea - random COSMOS
.container {
min-width: 130px;
max-width: 340px;
overflow: auto;
background: #999;
padding: 10px 40px;
resize: horizontal;
border: 1px solid #000;
}
.main-content {
display: flex;
flex-wrap: wrap;
background: #fff;
max-width: 340px;
overflow: hidden;
}
.child {
margin: 5px;
padding: 5px;
background: #99d9ea;
border: 1px solid black;
}
<div class="container">
<div class="main-content">
<div class="child">Foofoofoo</div>
<div class="child">Bar</div>
<div class="child">BazBaz</div>
<div class="child">QuuxQuuxQuux</div>
</div>
</div>
Resize the window or the above div to see the results
The above tells that the div is centered and the content is at left but not resizing according to content.
My personal opinion -
You should use @media
for making it responsize, just as the way you want it to be, It is just like coding a lot for a simple output but it can give you the best and satisfying results out of your hard work and time!
Kindly inform me if you want me to make it responsize for you, I mean just like a demo-
Regard,
Om Chaudhary
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With