Why Do Modern Browsers Still Put Spaces Between Inline Block If There Is Whitespace

Why is there an unexplainable gap between these inline-block div elements?

In this instance, your div elements have been changed from block level elements to inline elements. A typical characteristic of inline elements is that they respect the whitespace in the markup. This explains why a gap of space is generated between the elements. (example)

There are a few solutions that can be used to solve this.

Method 1 - Remove the whitespace from the markup

Example 1 - Comment the whitespace out: (example)

<div>text</div><!--
--><div>text</div><!--
--><div>text</div><!--
--><div>text</div><!--
--><div>text</div>

Example 2 - Remove the line breaks: (example)

<div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>

Example 3 - Close part of the tag on the next line (example)

<div>text</div
><div>text</div
><div>text</div
><div>text</div
><div>text</div>

Example 4 - Close the entire tag on the next line: (example)

<div>text
</div><div>text
</div><div>text
</div><div>text
</div><div>text
</div>

Method 2 - Reset the font-size

Since the whitespace between the inline elements is determined by the font-size, you could simply reset the font-size to 0, and thus remove the space between the elements.

Just set font-size: 0 on the parent elements, and then declare a new font-size for the children elements. This works, as demonstrated here (example)

#parent {
font-size: 0;
}

#child {
font-size: 16px;
}

This method works pretty well, as it doesn't require a change in the markup; however, it doesn't work if the child element's font-size is declared using em units. I would therefore recommend removing the whitespace from the markup, or alternatively floating the elements and thus avoiding the space generated by inline elements.

Method 3 - Set the parent element to display: flex

In some cases, you can also set the display of the parent element to flex. (example)

This effectively removes the spaces between the elements in supported browsers. Don't forget to add appropriate vendor prefixes for additional support.

.parent {
display: flex;
}
.parent > div {
display: inline-block;
padding: 1em;
border: 2px solid #f00;
}

.parent {    display: flex;}.parent > div {    display: inline-block;    padding: 1em;    border: 2px solid #f00;}
<div class="parent">    <div>text</div>    <div>text</div>    <div>text</div>    <div>text</div>    <div>text</div></div>

Display: Inline block - What is that space?

The space is in the HTML. There are several possible solutions. From best to worst:

  1. Remove the actual space in the HTML (ideally your server could do this for you when the file is served, or at least your input template could be spaced appropriately) http://jsfiddle.net/AWMMT/2/
  2. Use float: left instead of display: inline-block, but this has undesirable effects on t he height: http://jsfiddle.net/AWMMT/3/
  3. Set the container's font-size to 0 and set an appropriate font-size for the internal elements: http://jsfiddle.net/AWMMT/4/ -- this is pretty simple, but then you can't take advantage of relative font size rules on the internal elements (percentages, em)

How to remove the space between inline/inline-block elements?

Alternatively, you should now use flexbox to achieve many of the layouts that you may previously have used inline-block for: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


Since this answer has become rather popular, I'm rewriting it significantly.

Let's not forget the actual question that was asked:

How to remove the space between inline-block elements? I was hoping
for a CSS solution that doesn't require the HTML source code to be
tampered with. Can this issue be solved with CSS alone?

It is possible to solve this problem with CSS alone, but there are no completely robust CSS fixes.

The solution I had in my initial answer was to add font-size: 0 to the parent element, and then declare a sensible font-size on the children.

http://jsfiddle.net/thirtydot/dGHFV/1361/

This works in recent versions of all modern browsers. It works in IE8. It does not work in Safari 5, but it does work in Safari 6. Safari 5 is nearly a dead browser (0.33%, August 2015).

Most of the possible issues with relative font sizes are not complicated to fix.

However, while this is a reasonable solution if you specifically need a CSS only fix, it's not what I recommend if you're free to change your HTML (as most of us are).


This is what I, as a reasonably experienced web developer, actually do to solve this problem:

<p>
<span>Foo</span><span>Bar</span>
</p>

Yes, that's right. I remove the whitespace in the HTML between the inline-block elements.

It's easy. It's simple. It works everywhere. It's the pragmatic solution.

You do sometimes have to carefully consider where whitespace will come from. Will appending another element with JavaScript add whitespace? No, not if you do it properly.

Let's go on a magical journey of different ways to remove the whitespace, with some new HTML:

<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
  • You can do this, as I usually do:

     <ul>
    <li>Item 1</li><li>Item 2</li><li>Item 3</li>
    </ul>

http://jsfiddle.net/thirtydot/dGHFV/1362/

  • Or, this:

     <ul>
    <li>Item 1</li
    ><li>Item 2</li
    ><li>Item 3</li>
    </ul>
  • Or, use comments:

     <ul>
    <li>Item 1</li><!--
    --><li>Item 2</li><!--
    --><li>Item 3</li>
    </ul>
  • Or, if you are using using PHP or similar:

     <ul>
    <li>Item 1</li><?
    ?><li>Item 2</li><?
    ?><li>Item 3</li>
    </ul>
  • Or, you can even skip certain closing tags entirely (all browsers are fine with this):

     <ul>
    <li>Item 1
    <li>Item 2
    <li>Item 3
    </ul>

Now that I've gone and bored you to death with "one thousand different ways to remove whitespace, by thirtydot", hopefully you've forgotten all about font-size: 0.

Why is the browser injecting space into my LI?

That's because linebreaks are treated as a space in HTML. You've specified your inner elements to be inline-block, which means that spaces between them are displayed.

You can either:

  1. Set the font-size on the parent to 0, and then back to normal on the <li>,
  2. Simply eliminate the linebreaks between <li>s.

A third (lesser) option exists, it's the use of float.

float was originally meant to allow for elements to be pushed to the edges of the container, while having text flowing around it freely (like images in a newspaper). That feature was exploited used for layout as well, when people discovered it would make block level elements stack horizontally.

Using float would mean you need to clear after yourself, by either using a clearfix, or having an element with clear: both set on it.

This option is lesser, because much like tabular layouts, it's not the original purpose of float, implementation may differ between browsers and between time periods, but most importantly, it adds the overhead issues of clearing. (So stick with display: inline-block if you can help it!)

CSS: Why left border is taking extra space?

Please add the related code to your question

The reason there's a gap there is because the lis are set as display: inline-block. This means the browser treats them like words, and like words when there's a space between them the browser will render it. In your case the space comes from the newline and spaces used for indenting in the html.

Solution 1 (kinda hacky)

One solution which addresses this problem directly would be to add a:

#top-menu{
...
font-size: 0;
}

this essentially makes the space the browser is putting there have no font size which disappears it. Not perfect, but it addresses the problem directly. As @Kudla69 pointed out in his answer this does ruin font-size inheritance which can cause issues as well, which is what makes this particular hack not the recommended route.

Solution 2 Recommended

Another way to address this directly is to remove the space in the HTML. Restructuring the HTML to read more like.

<li> This is something
</li><li> This is something else
</li>

This removes the space between the elements and the browser will essentially treat them like words without a space between them and butts them right up against one another.

Solution 3

Finally, if you're fine with it, you can also float: left the li elements. This may cause sizing issues in some cases though. This removes them from the flow so the browser doesn't treat them like words anymore.

Or as others have said use display: flex which again can act a bit differently than inline-block at times but is a more modern approach.

Display Rules for Whitespace for Elements inside Inline Spans

An element that is display:inline-block is a inline-level, block container.

Like all block containers, it's made up of a vertical stack of line boxes. In your first case of the inline-block span, the stack is just one line box high.

The white-space rules apply to that line box. The rules state that:

As each line is laid out,

  1. If a space (U+0020) at the beginning of a line has 'white-space' set to
    'normal', 'nowrap', or 'pre-line', it is removed.
  2. All tabs (U+0009) are rendered as a horizontal shift that lines up the
    start edge of the next glyph with the next tab stop. Tab stops
    occur at points that are multiples of 8 times the width of a space
    (U+0020) rendered in the block's font from the block's starting
    content edge.
  3. If a space (U+0020) at the end of a line has 'white-space' set to
    'normal', 'nowrap', or 'pre-line', it is also removed.
  4. If spaces (U+0020) or tabs (U+0009) at the end of a line have
    'white-space' set to 'pre-wrap', UAs may visually collapse them.

So from rule 1 the space at the start of the span is "removed". Note that this is a layout behaviour. The space is still in the content, so when you copy and paste it the space is included.

In your second case, the space is between inline-block elements. It is neither at the start, nor end of the line, so it is not removed by the white-space layout rules.

In your third case, span elements are, by default, not block containers. They don't create a stack of line boxes, so the space is not at the start or end of a line box, and so it is not removed by the white-space layout rules.

Why does the browser renders a newline as space?

Browsers condense multiple whitespace characters (including newlines) to a single space when rendering. The only exception is within <pre> elements or those that have the CSS property white-space set to pre or pre-wrap set. (Or in XHTML, the xml:space="preserve" attribute.)

Why using flexbox in container can prevent extra space of inline-block

Flex layout is based on block layout. Whitespace is ignored in both of these layout modes.

But in inline layout, whitespace between inline boxes is significant as the whitespace is considered part of the inline content. As in my answer to your previous question, this is akin to having a phrase consisting of two words separated by a space — whitespace between two inline blocks behaves exactly the same as such a space.1

Flex layout and inline-blocks have absolutely no relation whatsoever and are not compatible with one another. When you declare display: flex on a container, its children become flex items, which can never be displayed inline (they can contain their own inline contents, however).


1 This is also why I contend that trying to remove whitespace between inline-blocks is really solving the wrong problem — you should never be using inline-block in the first place unless you well and truly understand inline layout and inline layout is actually what you need.

Why there is no gap between rows of less than 2 images?

It's happening because of vertical-alignment of an image in Quirks mode.

Check out these excerpts from this page:

Vertical alignment of an image is under certain conditions to the bottom of the enclosing box, not to the baseline of text. This happens when the image is the only content within an element, typically a table cell. This means that e.g. an image in a table cell is by default at the bottom of the cell in Quirks Mode (which is often what the author wants), whereas in Standards Mode there is a few pixels spacing below the image (unless one sets e.g. vertical-align: bottom for the img element).

I guess, when the images are wrapped and there's only one image per line, it behaves like the image is the only content within an element.

And this one from Wikipedia:

Another notable difference is the vertical alignment of certain types of inline content; many older browsers aligned images to the bottom border of their containing box, although the CSS specification requires that they be aligned to the baseline of the text within the box. In standards mode, Gecko-based browsers will align to the baseline, and in quirks mode they will align to the bottom.

Since the question is why this is happening, not how to solve it and there's already a few solutions in other answers, I won't add how to solve it.



Related Topics



Leave a reply



Submit