These are your layout requirements:
- three items per row
- each item is 192px wide
- the container is 608px wide
- the space between items must be 16px
- the space between items and the container must be 0px.
Well, you've already done the math, so you don't even need to use margins.
192 * 3 = 576
576 + 16 + 16 = 608
Since you've calculated the container's width to fit three items, plus an
extra 32px of free space, the margins are unnecessary. Use justify-content
, which is designed to distribute free space.
8.2. Axis Alignment: the justify-content
property
The justify-content
property aligns flex items along the main axis
of the current line of the flex container. [...] It helps distribute free space when all the flex items on a line are inflexible.
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between; /* NEW */
width: 608px;
background: #efefef;
}
.item {
flex: 0 0 192px;
border: 1px solid #ccc;
box-sizing: border-box;
}
<div class="container">
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
</div>
But your question ends with:
I'm curious if there is now a more elegant way to accomplish this with CSS3.
In cases where the item, spacing and/or container lengths vary, then YES.
Your goal, in essence, is to create "gutters", which means space between items, but not between items and the container.
Flexbox offers standard margins (which can cause trouble in multi-line containers, as you've seen) and alignment properties (like justify-content
and align-items
, which aren't precise unless you do the math beforehand).
Therefore, flexbox is not the optimal solution when gutters are important. It doesn't provide a natural method for creating space between items, without also applying that space between items and the container.
However, gutters are not a problem in CSS Grid Layout, which provides specific properties for horizontal and vertical gaps:
row-gap
column-gap
gap
(the shorthand for both)
These properties create space between grid items, but not between items and the container.
10.1. Gutters: the row-gap
, column-gap
, and gap
properties
The row-gap
and column-gap
properties (and their gap
shorthand), when specified on a grid container, define the gutters between grid rows and grid columns.
NOTE that the CSS Grid spec was recently revised. These properties were previously listed as grid-column-gap
, grid-row-gap
and grid-gap
(reference). I'm using these versions in the example below for compatibility purposes.
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 192px);
grid-column-gap: 16px;
width: 608px;
background: #efefef;
}
.item {
border: 1px solid #ccc;
box-sizing: border-box;
}
<div class="container">
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
<div class="item">Item</div>
</div>
Most major browsers now provide full support for CSS Grid.