29
votes

I'm trying to fiddle my problem on http://jsfiddle.net and have got strangest behaviour there. Can you please explain where these (http://jsfiddle.net/C6V3S/) vertical margins come from? Does appear on jsfiddle.net (at least in Chrome and FF), do not appear when copy/pasting to local standalone file ...

enter image description here

works OK afer changing to simple block enter image description here

Sample for standalone test file: .btn { padding: 0px; border: 1px solid red; display: inline-block; }

.txt {
    display: inline-block;
    width: 12px;
    height: 12px;
    border: none;
    padding: 0;
    margin: 0;
    background: #77FF77;
}
</style>

<div class="btn"><div class="txt"></div></div>
4
So, what is the problem ?user2196728
I had a similar issue, try out inline-flex, inline-table, see if those workmarkasoftware
yeah, jsfiddle.net/markasoftware/C6V3S/2 works with inline-flexmarkasoftware

4 Answers

33
votes

When you make the .txt element inline-block, it is taken into the text flow of the parent .btn element. At that point, the line-height of .btn kicks in, which is larger than the height of the .txt element.

So, add .btn {line-height: 10px;} (for example) and your problem is fixed. I saw you already tried to influence the line-height of the inner .txt element, so you were pretty close with your attempts. Adjusting the font-size would work as well, since the default line-height is formula-based on the font-size. Anyway, the key is to do that on the parent element, not the child element.

You don't have this problem when you make the inner element a block, because then there's no text-like content, so there's no line-height applied at all.

18
votes

inline-block is brilliant and convenient for so many cases. But they come with one annoying pitfall: unnecessary whitespace. As you're nesting an inline-block within an inline-block, that results in a white-space disaster. You can read all about whitespace and inline-blocks on David Walsh's blog.

There are many ways to handle this, but my favorite (and most widely supported) solution is setting this to the parent inline-block element:

.btn {
  font-size: 0;
}

Here is an example of before/after: http://jsfiddle.net/C6V3S/1/

3
votes

This is not caused by whitespace (you don't have any inside the divs in your HTML), nor by putting inline-block inside of another inline-block. This is caused because of the line-height of the outer div. As you can see from the below fiddle, the current line-height of the red-border div has a line-height that is being set by the browser (and it varies from browser to browser), and as long as there is something inside of the div that takes up space as an inline or inline-block item, the height will be affected by the line-height.

There are many ways around this, and they all pretty much do the same thing:

1) Take the inside element out of flow, and then reinsert it back in. This will make the outer div think that there is nothing inside of it, and try to become as small as possible, and then fill up space exactly around the element when it inserted back in. The easiest way to do this is by floating it.

2) Make the outer element take up no space. This will make the inside element define the height and width of its parent. If you do font-size: 0, as mentioned before, this will make the outer element think that the inline inside element takes up no space, and therefore not take up any space itself, and wrap itself tightly around the inner element. This can be done by setting line-height: 0 as well (which is a perfect fix for the problem, as the problem is line-height).

There are other ways to make the parent element not have its line-height, but that should get you started.

http://jsfiddle.net/C6V3S/4/

0
votes

It's "just how it works," but it can be worked around. The easiest way to fix it would be to set negative margins on .btn. It should work for any modern browser (IE8 and above, if I recall). Floating the elements should achieve what you want, too. As a wholly different solution if your problem with it is merely aesthetic, you can just wrap the elements in a parent, set that parent's background-color to what you want, and not worry about its child elements' backgrounds. They'll be transparent to whatever is beneath them, and you'll get rid of those visual breaks.

If you want to stick with negative margins on with display: inline-block, but need that pesky first element not to jump leftward out of its parent, you could target it explicitly:

.btn {
    margin-left: -4px;
}

.btn:first-of-type {
    margin-left: 0px;
}

Edit: After reading another answer, I'm not sure if I understood the question -- do you mean the margin atop the elements (which would be horizontal) or the margin to the sides (vertical)?