CSS Layouts are hard. Emerging standards like flexbox make them easier, but what if you need something that works in older browsers, Like IE8? This question led me to a pretty novel idea.
This is the layout I wanted to create. It's a simple grid with three items per row. Notice the kicker here, the first and last item in the row touches the very edge of the container.
1. Conditional Classes - Use the CMS to add a 'first-item' class to the first item and every subsequent 4th item. Also, add a 'last-item' class to every 3rd item to make the first and third items touch the boundaries of the container. This method relies on the CMS, which I didn't want to do, and it also doesn't work for responsive breakpoints.
2. nth-child(): Target every third item with the CSS nth-child selector. This is clean approach, and it's the one that Bootstrap uses. Unfortunately, IE8 doesn't support nth-child :(
3. negative margins: Add a wrapper around the items and give it a negative margin that offsets the margins of it's child items. This approach certainly works, but I've never been good at calculating negative margins, especially with flexible layouts.
4. flexbox: Sure, if IE anything support isn't an issue then go nuts. Unfortunately, given the IE8 requirement, flexbox is not an option.
When you think about it, the desired effect is similar to justified text, where the words of a block of text are spaced to the edges of their container. In this case though, each word would be the same width, so in theory, the space between each word should be identical.
The miracle of inline-block
Using inline-block, we can get our items to behave like words.
Using the little known 'text-align:justify' property, we can get our items to touch the edges of their container. If we make the items wide enough to only fit three items per line, then we get our desired effect.
The only thing we have to watch out for is that last line. Justified text doesn't space the last line to the edge of the container. To remedy this, we can add another inline-block with a 100% width after our items, using the CSS ':after' pseudo-selector. Which by the way, is fully supported in IE8.