I have been working on a website that displays products in a grid view, with each product containing a title, an image and some in a grid view. To achieve this layout, I used an unordered list with the CSS display
property on each item set to inline-block
. Let me walk you through the code and point out how this approach works well for a responsive layout.
Here’s a sample of the HTML for the list:
<ul class="products">
<li>
<a href="#">
<img src="shirt-gray.png">
<h4>Logo Shirt (Gray)</h4>
<p>$20.00</p>
</a>
</li>
<li>
<a href="#">
<img src="shirt-orange.png">
<h4>Mike the Frog Shirt (Orange)</h4>
<p>$25.00</p>
</a>
</li><!-- more list items -->
</ul>
Why Not Floats?
Your first inclination might be to use floats. Floating the list items works really well if each element has the exact same height. In most instances, though, that’s not the case. Even if they are all the same now, that might change in the future. When the items have different heights, you’ll see some weird stacking issues. (The second item is taller in my example. With floats that fifth item catches on it.)
Display Options
Instead of float, I give each list item a width and change the display from block to inline-block.
ul.products li {
width: 200px;
display: inline-block;
}
What exactly does this accomplish? Most HTML elements by default have a display property set block or inline:
- Elements with a display of
block
take up the full width of their parent elements and have their own horizontal line. - Elements with a display of
inline
take up only the space they need and can share their horizontal line with other elements.
A new block-level element will force a break to a new line. Think about paragraphs (<p> tags) as an example: any new paragraph starts a new line. Inline elements, on the other hand, can sit nicely on a line with other elements. Think about emphasis elements and links (<a> and <em> tags): a new inline element does notforce a new line. Take a look at this code example:
<p>This paragraph contains an <em>emphasis tag</em> and a <a href="#">link</a>.</p><p>This paragraph does not.</p>
<p>I think this orange one <img src="shirt-orange.png" alt="Mike the Frog, Orange"> is my favorite of all the shirts in Mike’s catalog.</p>
inline-block
is a third display option, and it unsurprisingly combines aspects of both the inline and the block options. The element sits inline just like an image does. But we can specify its height and width with CSS, and it can have block-level children elements that take up multiple lines inside of it.
<div>I think this orange one <div class="product"><a href="#"><img src="shirt-orange.png"><h4>Mike the Frog (Orange)</h4><p>$18.00</p></a></div> is my favorite of all the shirts in Mike’s catalog.</div>
vertical-align
CSS property.
ul.products li {
width: 200px;
display: inline-block;
vertical-align: top;
}
Responsive
This technique works nicely with a responsive layout. On a smaller screen, you might want to show only three products in a row instead of four. As the parent element gets smaller, the line will be shorter and items will naturally start wrapping to the next line earlier.
Caveat: One Big Drawback
If you put spaces or hard returns between two block-level elements, the browser ignores it. That means you can use spacing and indentation to make your HTML easier to read without having an effect on the display. With inline elements, that’s not the case. If you put a space between text or link tags, for example, the browser will display that space. The browser treats whitespace between two inline-block elements the same as it does inline elements. This makes sense if you think about it, but it means that you have to write the starting tag of a new element immediately after the previous ending tag to get the margins and padding to work like you would think. Here’s how I would modify my list to account for that:
<ul class="products">
<li>
<a href="#">
<img src="shirt-gray.png">
<h4>Logo Shirt (Gray)</h4>
<p>$20.00</p>
</a>
</li><li>
<a href="#">
<img src="shirt-orange.png">
<h4>Mike the Frog Shirt (Orange)</h4>
<p>$25.00</p>
</a>
</li><!-- more list items -->
</ul>
To me, this is a small price to pay to get the flexibility and responsiveness of inline-block for a product grid view like this.
Browser Support?
All modern browsers support the inline-block value for the display property. Internet Explorer 6 and 7 did not support it, but there was a simple hack you could use to get it to work. For old time’s sake, here’s the code:
ul.products li {
width: 200px;
display: inline-block;
vertical-align: top;
*display: inline;
*zoom: 1;
}