I have a bunch of same-size blocks set to display:inline-block
inside a div that has text-align:center
set to align the blocks.
| _____ _____ _____ _____ |
| | | | | | | | | |
| | 1 | | 2 | | 3 | | 4 | |
| |_____| |_____| |_____| |_____| |
| _____ _____ _____ _____ |
| | | | | | | | | |
| | 5 | | 6 | | 7 | | 8 | |
| |_____| |_____| |_____| |_____| |
| |
The blocks fill the div horizontally, and as the browser window shrinks, some blocks break to new lines, creating more rows and less columns. I want everything to still remain centered, with the last row aligned flush to the left, like this :
| _____ _____ _____ |
| | | | | | | |
| | 1 | | 2 | | 3 | |
| |_____| |_____| |_____| |
| _____ _____ _____ |
| | | | | | | |
| | 4 | | 5 | | 6 | |
| |_____| |_____| |_____| |
| _____ _____ |
| | | | | |
| | 7 | | 8 | |
| |_____| |_____| |
| |
What currently happens is this:
| _____ _____ _____ |
| | | | | | | |
| | 1 | | 2 | | 3 | |
| |_____| |_____| |_____| |
| _____ _____ _____ |
| | | | | | | |
| | 4 | | 5 | | 6 | |
| |_____| |_____| |_____| |
| _____ _____ |
| | | | | |
| | 7 | | 8 | |
| |_____| |_____| |
| |
I cannot add extra filler divs like one suggestion, because there could be any number of blocks, and the amount of rows and columns will vary depending on browser width. I also cannot style block #7 directly, for the same reason. The blocks must always remain centered no matter how many columns.
Here is a pen to better demonstrate:
http://codepen.io/anon/pen/IDsxn
Is this possible? I feel like it sure should be. I would prefer not to use flexbox as it is only ie10+, and I'd like ie9+. I would really like a pure CSS solution, but if you tell me JS is the only way, I'd love to see that in action.
For reference - similar questions, though none were thoroughly explained:
How to align left last row/line in multiple line flexbox
CSS - Left align the last row of images in a centered div
Center multiple inline blocks with CSS and align the last row to the left
With flexbox, some pseudo elements, an extra div, and after a lot of frustration I was able to achieve this without media queries (since I needed to put my grid inside many different sized elements, media queries wouldn't really work for me).
One caveat: gutters between items are fluid.
Demo: http://codepen.io/anon/pen/OXvxEW
CSS:
HTML:
The end result is something like this, where the green rectangles are divs. The pink/orange borders are just for reference so you can see what's going on. If you remove the pink/orange borders, you should get the grid you're looking for (though again, note that the gutter are fluid).
Here's a very simple JavaScript (and some small changes in your CSS) solution for you:
http://jsfiddle.net/ha68t/
It's working fine for me.
CSS:
JavaScript:
jQuery is required :)
Try this with simple css:
CSS:
.row{text-align:center;font-size:0;} .block{text-align:center;display:inline-block;width:150px;height:15px;margin:5px; border:1px solid #ffffdffffd;font-size:13px;}
HTML:
There is no "normal" solution for your problem, but only the mentioned "workarounds".
The situation is, your container of blocks will fill up available space up to the maximum available/set-up and then break all the inner blocks to the next line, which will cause the container have overflow. Also with other configurations like floating it will be the same behaviour. That's the way the rendering works - everytime greedy in space to calculate the inner elements behaviour.
Maybe the future Flexboxes will make this possible - but I did not read the full specs. Just a guess...
To date, the only clean solution for this is with the
CSS Grid Layout Module (Codepen demo)
Basically the relevant code necessary boils down to this:
1) Make the container element a grid container
2) Set the grid with an 'auto' amount of columns of width 120px. (The auto-fill value is used for responsive layouts).
3) Set gaps/gutters for the grid rows and columns.
4) and 5) - Similar to flexbox.
Codepen demo (Resize to see the effect)
Browser Support - Caniuse
Currently supported by Chrome (Blink) and Firefox, with partial support from IE and Edge (See this post by Rachel Andrew)
Further reading on CSS grids:
Solution with display inline-block
This adaptive grid is much simpler : less markup and less CSS so it will be easier to implement in a production site and adapt to your exact needs.
=>> DEMO <<= (resize the result window to see the effect)
It involves :
4 media queries for 200px wide blocks and a container expandable to 1000px. Depending on the width of your grid elements and the total width of your container you may have to make less or more
removing white-spaces between inline-block elements (in the following demo I used the font-size technique but you can use other ones (see How to remove the space between inline-block elements? for other techniques)
fixed margins between blocks
The number of blocks in one line adapts to the size of the container. The
text-align
property stay to default valueleft
so the last items are aligned to the left.Floats with adaptive margins between both blocks and container
=>> DEMO <<= (you need to resize the result window under 750px to see it in action)
This technique involves :
position:absolute;
:nt-child()
css selectorIt centers the blocks in their container and gives the same margin on the top/left/tight/bottom of all the blocks + sides of the container. As this solution uses floats, the last row is aligned to the left.
The number of blocks in one line adapts to the width of the window.