I'm currently on parental leave till September 1st. Until then, I will not be available to read comments, e-mails, tweets and Facebook messages.

If you are interested in my writings, please subscribe to my RSS feed and follow me on Twitter.

CSS display: inline-block: why it rocks, and why it sucks

Usually when you want a horizontal list, you need to use float in the CSS code to make it work, with all its drawbacks. However, there is an alternative with display: inline-block.

Problems with float

The problem when you have float in your CSS code is that you need to take some precaution to make the surrounding element to encompass the floated elements, and also to avoid following elements in the code to sneak up next to it. Another problem is that if you have a floated list that will take up several rows (visually speaking) and the content is of varying height, you are in for a world of hurt.

Enter display: inline-block

This is where the magic value inline-block for the display property comes into play. Basically, it’s a way to make elements inline, but preserving their block capabilities such as setting width and height, top and bottom margins and paddings etc. A simple example will look like this:

<style>
	ul#display-inline-block-example,
	ul#display-inline-block-example li {
		/* Setting a common base */
		margin: 0;
		padding: 0;
	}

	ul#display-inline-block-example li {
		display: inline-block;
		width: 100px;
		min-height: 100px;
		background: #ccc;
	}
</style>

<ul id="display-inline-block-example">
	<li>Item one</li>
	<li>Item two</li>
	<li>Item three</li>
</ul>

Rendered results

  • Item one
  • Item two
  • Item three

As you can see, display: inline-block; helps us here to render three square gray boxes next to each other. Awesome, right? However, with varying content, we need to add the property vertical-align: top to mkae sure everything is aligned to the top.

<style>
	ul#display-inline-block-example,
	ul#display-inline-block-example li {
		/* Setting a common base */
		margin: 0;
		padding: 0;
	}

	ul#display-inline-block-example li {
		display: inline-block;
		width: 100px;
		min-height: 100px;
		background: #ccc;
		vertical-align: top;
	}
</style>

<ul id="display-inline-block-example">
	<li>Item one</li>
	<li>Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two</li>
	<li>Item three</li>
</ul>

Rendered results

  • Item one
  • Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two
  • Item three

This will render just fine in Firefox, Safari, Google Chrome and IE 8. However, for older versions of Internet Explorer, we need to trigger hasLayout and also use a little hack to set the display to inline (note that this code could be in a separate stylesheet for IE, included via conditional comments – it’s inline here out of simplicity for this example):

<style>
	ul#display-inline-block-example,
	ul#display-inline-block-example li {
		/* Setting a common base */
		margin: 0;
		padding: 0;
	}

	ul#display-inline-block-example li {
		display: inline-block;
		width: 100px;
		min-height: 100px;
		background: #ccc;
		vertical-align: top;

		/* For IE 7 */
		zoom: 1;
		*display: inline;
	}
</style>

<ul id="display-inline-block-example">
	<li>Item one</li>
	<li>Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two</li>
	<li>Item three</li>
</ul>

Rendered results that will work in IE 7 too

  • Item one
  • Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two Item two
  • Item three

The enormous drawback

I hope so far that I have managed to get you to realize the potential and simplicity of this approach. However, there’s one giant drawback, that might or might not apply to your use case. That is, since the elements become rendered inline, white-space in your HTML code will affect the rendering. That means, if we want perfect size and alignment, but we have space between the LI elements in our code example, it will render a 4 pixel margin to the right of each element.

Case in point, let’s make it more clear by giving the surrounding UL element a fixed width, wherein the LI elements should fit:

<style>
	ul#display-inline-block-example,
	ul#display-inline-block-example li {
		/* Setting a common base */
		margin: 0;
		padding: 0;
	}

	ul#display-inline-block-example {
		width: 300px;
		border: 1px solid #000;
	}

	ul#display-inline-block-example li {
		display: inline-block;
		width: 100px;
		min-height: 100px;
		background: #ccc;
		vertical-align: top;

		/* For IE 7 */
		zoom: 1;
		*display: inline;
	}
</style>

<ul id="display-inline-block-example">
	<li>Item one</li>
	<li>Item two</li>
	<li>Item three</li>
</ul>

Rendered results

  • Item one
  • Item two
  • Item three

As you can see, the third item will now fall down to the next row. Which sucks! Hard! However, if we were to place the LI elements directly after each other, they would all be rendered in the same line:

<ul id="display-inline-block-example">
	<li>Item one</li><li>Item two</li><li>Item three</li>
</ul>

Conclusion

So, the conclusion is that white-space dependent rendering blows! But, there are also great possibilities with display: inline-block, so I advise you to try it out, play around with it and see if it works fine in your specific context.

Related reading

Cross-Browser Inline-Block

141 Comments/Reactions

  • #1 Mathias Bynens
    February 24th, 2010 at 11:53

    A little trick to overcome the white-space issue, but still have more or less readable/maintainable code, is to wrap line endings and indentation inside HTML comments:

    <ul id="display-inline-block-example"><!--
    --><li>Item one</li><!--
    --><li>Item two</li><!--
    --><li>Item three</li><!--
    --></ul>

    It still looks a little messy, but at least it’s more readable compared to a one-liner.

  • #2 Lars Gunther
    February 24th, 2010 at 12:09

    Or you could – gasp!- lose the end-tags…

    Was that me who said that? No….

  • #3 Morgan Roderick
    February 24th, 2010 at 13:07

    Very interesting post Robert!

    As usual, I have a few thoughts to add :-)

    White-space dependent rendering is usually a very-bad-idea[tm].

    Different developers might not understand that they’ve made invisible mistakes when updating your carefully crafted code. I am not suggesting we should cater to the lowest common denominator, but this shit is tricky to spot.

    Also, you have no control over what happens to your code once it leaves the server, different proxies do very different things to html, and then there is Opera Turbo … does anyone know how it treats whitespace? Some sites suggest that it uses OBML (Opera Binary Markup Language) to transfer pages … I wouldn’t be surprised to find that it “optimizes” whitespace.

    Furhtermore, the http://reference.sitepoint.com/css/display seems to suggest that IE7 automagically triggers hasLayout for elements with inline-block display, yet you set it in your example. Any thoughts on the different perceptions on this?

  • #4 David
    February 24th, 2010 at 13:11

    I use inline-block from time to time. It can save you a few lines of extra CSS, getting floats to behave. And I love how logical IE7 is — first you declare something inline-block, then switch it to inline to get it working, because that makes perfect sense.

  • #5 Robert Nyman - author
    February 24th, 2010 at 16:53

    Mathis,

    Good input! I have tested that approach, although it indeed feels quite messy.

    Lars,

    Man, that’s pragmatic. :-) But yes, it would work.

    Morgan,

    Thanks!
    And yes, white-space dependent code sucks, and with the associated trickery, it becomes a maintenance/code handover risk.

    With IE 7, in my testing at least, setting hasLayout and changing display to inline has been necessary.

    David,

    Yeah, IE 7 is a mess… :-)

  • #6 ytzong
    February 25th, 2010 at 2:35

    this can fix the last problem

    ul{letter-spacing:-.25em}
    li{letter-spacing:normal;}

    ul’s letter-spacing value is different by font, it may be:
    Verdana -.5em
    Arial -.25em
    Tahoma -.333em

    see more http://www.99css.com/?tag=inline-block
    you can translate it from chinese to english by using google translate:)

  • #7 Robert Nyman - author
    February 25th, 2010 at 10:18

    ytzong,

    Interesting! I need to experiment with that!

  • #8 Thomas
    February 25th, 2010 at 10:56

    I recently used “display:inline-block” and came the same conclusion.

    I have another fix to propose:
    ul{font-size:0}
    li{font-size:13px;}

    In theory you should not be bothered anymore with white-spaces.

  • #9 Robert Nyman - author
    February 25th, 2010 at 13:48

    Thomas,

    Cool, another option to test!

  • #10 ytzong
    February 25th, 2010 at 14:23

    @Thomas
    Google’s Chrome Browser can’t define font-size which value less then 12px at least on chinese version, so your method would be unavailable

  • #11 John Faulds
    February 25th, 2010 at 23:43

    The white-space issue is also apparent when using display: inline.

  • #12 Robert Nyman - author
    February 26th, 2010 at 9:02

    ytzong,

    Interesting, didn’t know that about Google Chrome.

    John,

    Absolutely, good point.

  • #13 Peter Weil
    February 26th, 2010 at 14:12

    I’ve been using this approach a lot more recently — for layout as well as lists — and I really don’t see the white space thing as a serious issue. You just need to be aware of it. And while floats can be made to work in these types of situations, they feel more “hackish” to me and can be a real pain.

  • #14 Robert Nyman - author
    February 26th, 2010 at 15:49

    Peter,

    Right, getting floats to behave exactly as desired can definitely be a pain.

  • #15 CSS display: inline-Block: Why It Rocks, And Why It Sucks « Ronald Jusuf's Virtual Ramblings
    February 27th, 2010 at 14:24
  • #16 Jan Van Lysebettens
    February 27th, 2010 at 15:29

    Just wondering, but wouldn’t the whitespace property applied to the ul tag be helpfull ?
    Didn’t test it out or anything, just a hunch :)

  • #17 Jon_E
    February 27th, 2010 at 19:59

    I just happened to be visiting this page using an old Mozilla 1.7 browser. Lotsa rendering problems here.

  • #18 Sarven Capadisli
    February 27th, 2010 at 21:21

    :before { content:'\0009'; } is one way to fake whitespace (e.g., indenting) if it is not in HTML.

  • #19 Mathias Bynens
    February 28th, 2010 at 11:30

    Here’s another fix for the problem, using a monospaced font and negative values for margin-left and margin-right: http://nerd.vasilis.nl/remove-whitespace-inline-block/

  • #20 CSS display: inline-block: why it rocks, and why it sucks | Dev Loom
    March 1st, 2010 at 9:32

    [...] CSS display: inline-block: why it rocks, and why it sucks Via / CSS Globe [...]

  • #21 Robert Nyman - author
    March 1st, 2010 at 11:35

    Jan,

    It’s an interesting thought, but apparently it can’t be used to remove white-sapce.

    Jon_E,

    Yes, since this is a private web site, there’s no time or need, from my point of view, to adapt a design to a web browser used by less than 0.01% of my visitors.

    Sarven,

    It’s interesting, but only in web browsers that support the :before pseudo protocol.

    Mathias,

    Interesting! Seems a bit tricky, but might be a viable option. Thanks!

  • #22 Jordan Walker
    March 1st, 2010 at 15:44

    This is a great article about css inlin display, very helpful and informative.

  • #23 Robert Nyman - author
    March 1st, 2010 at 15:47

    Jordan,

    Thank you!

  • #24 dougwig
    March 1st, 2010 at 17:15

    Display:inline-block is also handy when you want to align traditionally block-level content ( say a list or a small form ) within a line-box ( The block level parent ). Remember vertical-align:middle or text-align:center ? This all works with elements that are display:inline-block. Rarely needed, but nice to have when you need it.

  • #25 Robert Nyman - author
    March 1st, 2010 at 17:18

    dougwig,

    Absolutely, good point!

  • #26 CSS Brigit | CSS display: inline-block: why it rocks, and why it sucks
    March 2nd, 2010 at 14:31

    CSS display: inline-block: why it rocks, and why it sucks…

    Usually when you want a horizontal list, you need to use float in the CSS code to make it work, with all its drawbacks. However, there is an alternative with display: inline-block….

  • #27 Anders
    March 2nd, 2010 at 21:34

    inline-block is the shizzle! In my opinion floats were never meant to be used as a complex layout mechanism, but rather for having text wrap around images and stuff like that.

    One huge advantage is that it removes all the hassle of clearing. On the downside though is the gap issue that you mentioned. Is there any logical reason as to why it should behave that way?

  • #28 Robert Nyman - author
    March 3rd, 2010 at 9:44

    Anders,

    Yep, the gap is the only actual issue with it. I believe it comes from a long, troublesome heritage of respecting white-space between inline elements, which is, if you ask me, a terrible thing.

  • #29 Christophe
    March 4th, 2010 at 19:25

    Hi there,
    i’m not exactly sure (I’m french) to understand, but problems I often encountered with float, came from “clear” property from the parent element.
    To solve it, I use “overflow:hidden” property on parent element, for exemple :

    ul#display-inline-block-example,
    ul#display-inline-block-example li {
    /* Setting a common base */
    margin: 0;
    padding: 0;
    }

    ul#display-inline-block-example {
    display: block;
    position:relative;
    overflow:hidden;
    width:100%;/*for exemple*/
    }

    ul#display-inline-block-example li {
    float:left;
    width: 100px;
    min-height: 100px;
    background: #ccc;
    }

    What do you think about this tip ?

  • #30 Robert Nyman - author
    March 5th, 2010 at 9:32

    Christophe,

    Using overflow: hidden to make a parent element contain all its floated children elements is a great approach, but it won’t be sufficient when the floated children span across multiple rows and and when the items aren’t of equal height.

  • #31 tOM Trottier
    March 7th, 2010 at 3:42

    Tables! Let do all the work!

    tOM

  • #32 tOM Trottier
    March 7th, 2010 at 3:44

    (actually meant <td>)

  • #33 Robert Nyman - author
    March 8th, 2010 at 10:01

    tOM,

    Well, there are a number of downsides to that to, in terms of semantic value and representation, certain lack of width control etc.

  • #34 display:inline-block; ??? | css | understandard.net
    March 23rd, 2010 at 9:21

    [...] ???????float:left; ????display:inline-block; ????????? ?????CSS display: inline-block: why it rocks, and why it sucks [...]

  • #35 What is Inline-Block? | Impressive Webs Toronto
    April 26th, 2010 at 22:03

    [...] According to Robert Nyman: Basically, it’s a way to make elements inline, but preserving their block capabilities such as setting width and height, top and bottom margins and paddings etc. [...]

  • #36 Ningbo Hotels
    June 1st, 2010 at 17:59

    Hi Robert!

    Thank you for this interesting article!
    For my personal usage, “display: inline” rocks :-)

    I use it to get perfect images gallery and I align for example 3 thumbnails horizontally on a line with equal space on the left and right of my pics.

    My CSS code is very simple as I use a “float:left;” with “width:33%;” and an img class including “display: inline”.
    I used to have display:block and my thumbnails were not perfectly centered. When I switched to inline, they just moved to a perfect equally aligned position.

    So for me, yes this is a magic value :-)

    Cheers!
    Roger

  • #37 Robert Nyman - author
    June 2nd, 2010 at 0:08

    Roger,

    Glad you liked it!

  • #38 Matbaa
    July 9th, 2010 at 15:23

    Thank you.

    /* For IE 7 */
    zoom: 1;
    *display: inline; was important for me.

  • #39 My bookmarks for 07/25/2010 | SiliconChaos
    July 25th, 2010 at 13:33

    [...] » CSS display: inline-block: why it rocks, and why it sucksRobert’s talk – Web developm… [...]

Write a comment

Twitter reactions

Share your thoughts:

HTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> . If you want to display code examples, please remember to write &lt; for < and &gt; for >.

Comment preview