Site icon Treehouse Blog

Using inline-block to Display a Product Grid View

Screenshot of T-Shirt Store

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.) To adjust for this, I’ve seen people wrap each row in a separate div or add clears to the first item in each row. But these adjustments force your layout to have a set number of columns, making it less adaptable in the changing layouts of responsive design.

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:

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>

Images are inline elements. If you put an image in the middle of a string of text, it will sit inline with that text.

<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&rsquo;s catalog.</p>

Note that the image is taller than the text. Inline elements do not need to be the same height to sit on a line together. The shorter elements on the line will just have blank space above or below them. Each line of text starts fully below the previous one. inline-blockis 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&rsquo;s catalog.</div>

To achieve the grid view, we set every list item to display as inline-block. Just like words in a paragraph, products will appear next to each other; when there’s no room on a line for another product, the next product will simply wrap to the next line. With items of different heights, you’ll usually want the top edge of them to line up. This doesn’t happen by default, but you can easily modify that with the vertical-alignCSS 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;
}
Exit mobile version