About inline-blocks

We can use inline-blocks to make HTML-elements appear side-by-side on a webpage. It seems that they’ve gained popularity as an alternative to using floats. In this post we’ll have a look at how to use them and how to deal with their challenges.

The basics

Essentially HTML elements can be either ‘block-level’ or ‘inline’ elements. An inline-block behaves as a combination of both. It is actually an inline-element that behaves as a block-level element on it’s inside. To better understand the properties of inline-blocks let’s have a look at the main characteristics of both block-level and inline elements.

Inline elements

  • The display property has a value of inline
  • Boxes have the width of their contents
  • Boxes are laid out horizontally starting at the top
  • Vertical margins can’t be specified
  • Width and height can’t be specified
  • The direction and text-align properties can be used to control positioning
  • Left and right margins can be used to control horizontal positioning
  • The vertical-align property can be used to control vertical positioning

Block-level elements

  • The display property has a value of blocklist-item or table
  • Boxes by default span the entire width of their container
  • Boxes are laid out vertically, starting at the top
  • Width and height can be specified
  • Margins can be used to control positioning

Display: inline-block

We can make elements behave as inline-blocks by setting the display property to inline-block:


a { display: inline-block; }

Internet Explorer 6 and 7 do not support the value inline-block for elements that are not inline by default. There’s an easy workaround for this:


div {
  display: inline-block;
  *zoom: 1; /* trigger hasLayout for IE7 and below */
  *display: inline; /* the star targets only IE7 and below */
}

After this, the boxes will have the folowing characteristics:

  • Boxes are laid out horizontally
  • Width and height can be specified
  • Margins can be used to control the positioning
  • The vertical-align property can be used to control vertical positioning

Why use them

You can use inline-blocks to set a width/height or vertical margins on an inline-element and still keep it inline. They also have some advantages compared to floats, for example:

  • The elements remain part of the document flow so there’s no need for clearfixes
  • We have more control over the vertical alignment by using the vertical-align property with the values topmiddle and bottom
  • No extra markup or clearing is needed when the columns contain elements of varying height
  • Centering a grid-column can be done both with text-align: center or setting margins

Whitespace

When elements are rendered as inline-blocks on your screen you’ll find that the sides of the boxes don’t ‘touch’ each other. There’s always a small ‘whitespace’ along the side of the boxes. This is the spacing that’s needed to seperate characters and words from each other in a sentence. It’s the ‘inline part’ of inline-blocks. Even on a page that contains only boxes and no text, setting the display value to inline-block will insert whitespaces. These spaces come from the characters you use to format the code in your editor, the spaces, tabs and newlines. We are happy to have this space when inserting a link for some word in a sentence but when doing a grid layout for example they are a real pain.

There are several methods that deal with removing or negating this whitespace. I’ve summed them up below.

Remove whitespaces


<ul>
  <li>Lorem.</li><li>Sapiente!</li><li>Repudiandae?</li><li>Veniam!</li><li>Dolorum.</li>
</ul>

Whitespace within tags


<ul>
  <li>Lorem.</li><li>
  Sapiente!</li><li>
  Repudiandae?</li><li>
  Veniam!</li><li>
  Dolorum.</li>
</ul>

Whitespace within comments


<ul>
  <li>Lorem.</li><!--
--><li>Sapiente!</li><!--
--><li>Repudiandae?</li><!--
--><li>Veniam!</li><!--
--><li>Dolorum.</li>
</ul>

Font-size zero


ul {
  font-size: 0;
}
ul li {
  display: inline-block;
  font-size: 16px;
}

This method works by setting the fontsize of the parent to zero. The size of the whitespace depends on fontsize so when we set the fontsize to zero the space is negated. This solution is difficult when working with relative units like ems because if the font-size on the parent is set to zero, all em based values like padding will also be set to zero. However it does work with the rem (root em) unit.
This solution doesn’t seem to work well in Android Internet. I tested this with Android versions 2.2, 2.3.3, 4.1, 4.2 and 4.3 and all of them showed issues. Android 2.2 and 2.3.3 seemed to completely ignore the parent/child fontsize thing breaking the entire layout. In Android 4.1, 4.2 and 4.3 whitespaces were not completely negated. A row with 3 blocks (one-thirds) worked as expected but a row with 4 boxes (one-fourths) would shift the last box to the row below.

Negative right margin


li {
  display: inline-block;
  margin-right: -0.25em;
}

This method negates whitespace by setting a negative value for the right margin that is at least equal to the size of the whitespace. Finding the optimal value for the margin is not that straightforward. I found that the value that negates the whitespace differs amongst different browsers and depends not only on the fontsize but also on the zoomlevel that is used to view a page.

The invisible font

In the comments below Rude pointed out another technique for dealing with the whitespace issue. This method works by including an icon-font of which the characters have zero width and applying that on the parent element. This way no whitespaces are introduced. Follow the link in his comment to see it in action.

Open tags

Mundi left a comment with this approach. If we omit the closing tags, no spaces are introduced.


<ul>
  <li>One
  <li>Two
  <li>Three
</ul>

It may not win the beauty contest but it passes validation for HTML documents (not XHTML).

Remove whitespace with JavaScript

It’s also possible to remove unwanted nodes (spaces) with JavaScript. David (see his comment below) has created a nice demo:  http://codepen.io/hucklesby/pen/sDGaC.

The optimal margin size for negating whitespace

What is the right margin size to make whitespaces disappear in different browsers? I did some tests to find the optimal value for the five main desktop browsers. For this purpose I created a a simple two-column layout with inline-blocks, negating the whitespace with the margin-right ‘method’. I then viewed the page with different margin-values, font-size and zoomlevels. I also found that resizing the width of the browserwindow did matter as it sometimes made the whitespace visible/invisible. If there was visible whitespace present anywhere from the minimum to the maximum zoomlevel, then the browser failed the test for that margin size. When there was no visible whitespace I marked the browser as ‘passed’ for that margin-size. The tables below show the margin sizes at which the browsers did pass the test (marked in green).

All browsers except Internet Explorer were used on OSX 10.9.1.
Internet Explorer was used on Windows 8 Pro.

Margin size needed to negate whitespace
Fontsize:
9px
Margin value (em)
-0.24 -0.25 -0.26 -0.27 -0.28 -0.32 -0.34
Chrome 32.0
Firefox 26.0
IE 10.0
Safari 7.0.1
Opera 12.16
Margin size needed to negate whitespace
Fontsize:
standard
Margin value (em)
-0.24 -0.25 -0.26 -0.27 -0.28 -0.32 -0.34
Chrome 32.0
Firefox 26.0
IE 10.0
Safari 7.0.1
Opera 12.16
Margin size needed to negate whitespace
Fontsize:
72px
Margin value (em)
-0.24 -0.25 -0.26 -0.27 -0.28 -0.32 -0.34
Chrome 32.0
Firefox 26.0
IE 10.0
Safari 7.0.1
Opera 12.16

The values that negate whitespace range from -0.24em to and including -0.34em. This covers the major desktopbrowsers and fontsizes from 9px to 72px. Now let’s have a look and see what happens if we set the right margin to -0.32em (pixelperfect in Opera for standard fontsize) and open up the page in IE  that needs only a margin of -0.24em.

The blue line in the enlarged area is box number 2 selected in IE developer tools. It shows the right box overlapping the left one with more than a pixel (0.32 – 0.24 * 16 = 1.28px).
Maybe the best way to deal with whitespace is just not using whitespace at all. For the more important parts of a webpage like a grid layout for example I think the ‘whitespace within comments’ would be a better option. Although this has maintainability issues, I think it’s by far the most solid option as it actually keeps the whitespace out of your code.

A layout with inline-blocks

Let’s see inline-blocks in action and create a grid layout. I used the HTML-comments solution to keep whitespace out. The first row show the boxes vertically aligned in the middle. This is the default behaviour but can also be set with vertical-align: middle. Rows 3 and 4 show the boxes with vertical-align: top and vertical-align: bottom. Centering the box (row 6) is done with text- align: center set on the wrapper (.grid).

1/4
1/4
1/4
1/4
1/3
1/3
1/3
1/4
1/4
1/4
1/4
1/4
1/4
1/4
1/4
2/4
2/4
2/4


<div class="grid">
 <div class="grid-cel fourths-1">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel thirds-1">
      <div class="module">1/3</div>
    </div><!--

 --><div class="grid-cel thirds-1">
      <div class="module">1/3</div>
    </div><!--

 --><div class="grid-cel thirds-1">
      <div class="module">1/3</div>
    </div><!--

 --><div class="grid-cel fourths-1 top">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 top">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 top">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 top">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 bottom">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 bottom">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 bottom">
      <div class="module">1/4</div>
    </div><!--

 --><div class="grid-cel fourths-1 bottom">
      <div class="module">1/4</div>
    </div><!--

  --><div class="grid-cel fourths-2 left">
       <div class="module">2/4</div>
     </div><!--

  --><div class="grid-cel fourths-2">
       <div class="module">2/4</div>
    </div><!--

  --><div class="grid-cel fourths-2 right">
       <div class="module">2/4</div>
     </div>
</div><!-- end of .grid -->


/**
 * General
 */

/* Changing the box-model to border-box*/

* {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

/**
 * Grid
 */

.grid {
  text-align: center;
  padding: 0 0 0 1.25em;
}
.grid-cel {
  display: inline-block;
  padding: 0 1.25em 0 0;
  text-align: left;
  *zoom: 1;
  *display: inline;
}

/* Vertical alignment */

.grid-cel.top {
  vertical-align: top;
}
.grid-cel.bottom {
  vertical-align: bottom;
}

/* Thirds */

.thirds-1 {
  width: 33.333333%;
}

/* Fourths */

.fourths-1 {
  width: 25%;
}
.fourths-2 {
  width: 50%;
}

.fourths-2.left {
  margin-right: 50%;
}
.fourths-2.right {
  margin-left: 50%;
}

/**
 * Content
 */

.module {
  margin: 0 0 1.25em;
  text-align: center;
  line-height: 4.166666666666667;
  background-color: #dedede;
}

/* Simulate content height */
.grid-cel:nth-child(2) .module,
.grid-cel:nth-child(10) .module,
.grid-cel:nth-child(14) .module {
  line-height: 5.555555555555555;
}
.grid-cel:nth-child(3) .module,
.grid-cel:nth-child(9) .module,
.grid-cel:nth-child(13) .module {
  line-height: 6.944444444444445;
}
.grid-cel:nth-child(4) .module,
.grid-cel:nth-child(8) .module,
.grid-cel:nth-child(12) .module {
  line-height: 8.333333333333334;
}

More information

  • There are a some CSS/grid frameworks that rely on inline-blocks instead of floats. For example Inuit and Griddle.

0 comments

  1. Mundi Morgado

    04-02-2014

    When using inline block list elements, you can omit the closing tag and not worry about the whole white-space issue…

    
    <ul>
      <li>one
      <li>two
      <li>three
    </ul>
    
    

    Some people find that gross, however it’s perfectly valid and works back to IE8. most importantly, it’s less code

  2. _diondiondion

    04-02-2014

    It might be worth noting that the display: table property actually acts different from other block elements in that they don’t automatically span the whole width of their container.

  3. Yotam

    04-02-2014

    Great writeup!

    It’s about time someone did a comprehensive write up about this fantastic css property.

    You might also want to mention that using server side code you can output multiple elements by placing the opening and closing tags of the loop right before and after the element itself.
    Take a look at this gist for an example:
    https://gist.github.com/hitautodestruct/8800789
    Notice the opening and closing of the php tags.

    And this is also a great technique which utilizes inline-block
    http://css-tricks.com/centering-in-the-unknown/

  4. MO

    04-02-2014

    And what about:
    white-space: nowrap;

  5. Christian van Deursen

    04-02-2014

    Thank you Rude for this link. Very helpfull.

  6. David Hucklesby

    04-02-2014

    I don’t think there’s a foolproof method. A couple of additional ideas though:

    1. Minify your HTML
    2. Use JS to delete the spaces (text nodes) –
    Demo: http://codepen.io/hucklesby/pen/sDGaC

  7. Nikolay

    04-02-2014

    There is another good technique to avoid whitespace. It is the letter-spacing: -0.31em; on and letter-spacing: normal; on nested

  8. md Tobarak hossain

    08-02-2014

    very good lesson. thanks

  9. Leevi Graham

    04-05-2014

    A deal breaker with inline-block grids could be printing in firefox.

    Long inline blocks that span multiple pages are cropped after the first page.

  10. Tiago Celestino

    13-03-2016

    Nowadays, flexbox is a better solution for that.

Comments are closed.