20

Please read the question carefully. It's not the same as the one about How to remove the space between inline-block elements.

Consider the following HTML:

body {
  /* font-family: Arial; */
}

.my-class {
  display: inline-block;
  margin: 0 0 0 -4px;
  background-color: transparent;
  border: 1px solid #ccc;
  padding: 20px;
}
<div>
  <button class="my-class">Hello</button>
  <button class="my-class">Stack</button>
  <button class="my-class">Overflow</button>
</div>

Which produces:

screenshot 1

But, if I add:

body {
  font-family: Arial;
}

it results in a 1px space between the second and third buttons:

screenshot 2

The question is: Why adding font-family to the body affects the space between the buttons?

Salman A
  • 262,204
  • 82
  • 430
  • 521
Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • 4
    try this: delete spaces between close and open button tags -> – mohsen dorparasti Oct 15 '14 at 06:16
  • 1
    the above answers are correct, the reason behind that is each and every browser has its own setting for rendering a page, better globally set font-size (ex: body{font-size:12px;}) may avoid these kind of issues!! – Aru Oct 15 '14 at 06:27
  • The `` element is used to denote user input, **not** hyperlinks. Please don't decorate your hyperlinks with these. – James Donnelly Oct 15 '14 at 08:45
  • @Aru That's interesting! Could you elaborate on that or provide some references? – Misha Moroshko Oct 15 '14 at 09:56
  • @MishaMoroshko, check these articles http://meyerweb.com/eric/thoughts/2007/04/18/reset-reasoning/ and http://meyerweb.com/eric/tools/css/reset/ and http://www.smashingmagazine.com/2010/06/07/the-principles-of-cross-browser-css-coding/ – Aru Oct 15 '14 at 10:09
  • I'm getting some mixed results from your demo. At first it has messed up spacing, after messing around with things for a while it seems to fix itself. Weird – Zach Saucier Oct 18 '14 at 04:46
  • On chrome 39 beta, there is no difference if I add the font-family. – Ian Hazzard Oct 18 '14 at 21:21
  • Most importantly is to know, what browsers/devices/platforms can you reproduce the issue? Your [demo](http://jsbin.com/bulowuvavepa/1/edit) works just the same with or without `font-family` in Firefox 33.0, Chrome 38.0.2125.104 m, Opera 12.17 [1863], Opera 25.0.1614.50 and Safari 5.1.7(7534.57.2) (all Windows) – JFK Oct 19 '14 at 08:20

8 Answers8

28

It happens because each font has different width, even for the space character. You already know about the whitespace issues with inline-blocks. So, when you set Arial, those whitespaces change their width slightly from the browser's default font (or any other font with different width), which is Times New Roman in my case.

See how drastic the change is when you set the monospace font.

Now, why it happens between the 2nd and the 3rd box and not the 1st and the 2nd one? I'm pretty sure it comes down to rounding pixel values based on the width of the words entered, seems like there is a pseudo sub-pixel rendering present in the background, yet the decimal values get rounded in the final render process. See what happens if you use Arial and print Hell Stack Overflow instead of Hello Stack Overflow - the gaps look the same. So, it's just an undesired coincidence.

Another point that proves this is a rounding issue is the change in the gaps across various page zoom levels. It's fairly common to get these pixel mismatches in the layout when dealing with decimals in HTML. Zooming adds another dividing/multiplication stage, which changes the core values even further, resulting in completely unpredictable behaviour in the final layout.

Shomz
  • 37,421
  • 4
  • 57
  • 85
  • 2
    Btw. I doubt you'll ever get `an answer drawing from credible and/or official sources` because it's a combination of answers about 3-4 different topics (some of which could differ from browser to browser quite possibly), so summing those into one solid answer would look iffy, at best. – Shomz Oct 18 '14 at 14:55
  • 2
    Honestly, I didn't like **any** of the other answers so I didn't upvote any of them because they are all too focused on what OP **clearly** stated we should not talk about: the whitespace issue with inline-blocks and how to fix it. And @dippas, about 90% of your answer is about that as well, so I can see why you could get downvoted. – Shomz Oct 18 '14 at 17:30
  • 4
    +1 for mentioning the rounding off issue as a possible cuplrit. – Salman A Oct 20 '14 at 13:50
11

It's because you're displaying the buttons as inline-block elements and when you have inline elements whitespace is significant and is rendered in the same way that spaces between words is rendered.

i.e inline-block makes whitespace significant, so spaces in the source between inline-block elements will be rendered.

For example: You could center the inline-block elements just by adding text-align: center; the same way is used to center the text in its parent block element. - DEMO

Why adding font-family to the body affects the space between the buttons?

Different fonts can have different spacing between words, If you compare font-family: monospace; with font-family: sans-serif; then you will see the monospace fonts have more space between words than sans-serif fonts and the inline-block elements is also rendered in the same way and have the spacing between elements.

The best way to remove the space between inline-block elements is adding the font-size: 0; to the parent element.

DEMO

div {
  font-size: 0;
}
.my-class {
  display: inline-block;
  border: 1px solid #cccccc;
  padding: 20px;
  font-size: 16px;
}
<div>
    <button class="my-class">Hello</button>
    <button class="my-class">Stack</button>
    <button class="my-class">Overflow</button>
</div>
Anonymous
  • 10,002
  • 3
  • 23
  • 39
  • 2
    Does not explain why the spacing is inconsistent (which is the actual question). – Salman A Oct 21 '14 at 04:24
  • The spacing between inline-block elements is equivalent to the width of one character on the inherited font, so I tried to compare two fonts that have different spacing between words by showing inline-block rendered the same way and have different spacing between elements as per the font-family, so margin -4px doesn't help to remove the spacing between inline-block elements. Please correct me if I'm wrong. :) – Anonymous Oct 21 '14 at 04:55
  • An important bit in the question is that `-4px` covers the gap between first and second button but not between second and third. Inherited font and size are the same but spacing is inconsistent. – Salman A Oct 21 '14 at 05:12
8

The answer assumes that DirectWrite is enabled. You will not notice the specified symptoms and fractional widths otherwise. It is also assumed that default serif and sans-serif fonts are Times New Roman and Arial.


Whoever said that the space character is 4px wide is mistaken:

$(function() {
    $(".demo").each(function() {
        var width = $("span", this).width();
        $("ins", this).text("total width: " + width + "px, " + (width / 10) + "px per space)");
    });
});
.demo {
    white-space: pre;
    overflow: hidden;
    background: #EEE;
}
.demo-1 {
    font: 16px/1 sans-serif;
}
.demo-2 {
    font: 16px/1 serif;
}
.demo-3 {
    font: 16px/1 monospace;
}
.demo span {
    float: left;
    background: #CF0;
}
.demo ins {
    float: right;
    font-size: smaller;
}
<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<p>The green blocks contain 10 spaces:</p>
<p class="demo demo-1"><span>          </span><ins></ins></p>
<p class="demo demo-2"><span>          </span><ins></ins></p>
<p class="demo demo-3"><span>          </span><ins></ins></p>

Note that:

  1. For a given size the character width depends on font family.
  2. The character width does not necessarily have to be a whole number. Serif font gives you a nice whole number (4px), but Sans-serif font gives you fractional number (4.4px).

You could get different results in different browsers depending on how they handle fractional gaps between two blocks (e.g. 4.4px for 16px Arial). CSS specs are silent about this.

In Chrome with DirectWrite enabled, spaces are rendered as 4px and 5px alternately due to rounding off. This explains why there is no gap between first and second button and 1px gap between second and third. Try adding more buttons in your original example and notice how the pattern repeats (Demo).

Using margin-left: -4.4px seems to work but it is not guaranteed to work. Consider going back to the alternate solutions.

Community
  • 1
  • 1
Salman A
  • 262,204
  • 82
  • 430
  • 521
5

PROBLEM:

this happens because the display is set to inline-block.

inline-block is:

The element generates a block element box that will be flowed with surrounding content as if it were a single inline box (behaving much like a replaced element would)

»» see more about display property here: DISPLAY INFO

SOLUTION(S):

  • Remove the spaces
  • Negative margin
  • Skip the closing tag
  • Set the font size to zero
  • Just float them instead
  • Just use flexbox instead

For more details on each solution check

Fighting the Space Between Inline Block Elements

my preferred solutions from above is

Set the font size to zero

therefore is a snippet with your code and my preferred solution:

div {
 font-size:0;
}

.my-class {
  display: inline-block;
  border: 1px solid #cccccc;
  padding: 20px;
  font:normal 12px Arial;
}
<div>
  <button class="my-class">Hello</button>
  <button class="my-class">Stack</button>
  <button class="my-class">Overflow</button>
</div>

Plus, here is a snippet with your EXACT CODE only changing the font-family from body to the elements that have display:inline-block, and achieving the same output as my FIRST SNIPPET

.my-class {
  display: inline-block;
  margin-left: -4px;  /* Remove the space between inline elements */
  border: 1px solid #cccccc;
  padding: 20px;
  font-family:Arial;
}
<div>
  <button class="my-class">Hello</button>
  <button class="my-class">Stack</button>
  <button class="my-class">Overflow</button>
</div>

EDIT:

OP's question:

Why adding font-family to the body affects the space between the buttons?

in web typography there are:

  • Sans-serif

    Fonts that do not have decorative markings, or serifs, on their letters. These fonts are often considered easier to read on screens.

  • Serif

    Fonts that have decorative markings, or serifs, present on their characters.

  • Monospace

    Fonts in which all characters are equally wide.

  • Cursive

    Fonts that resemble cursive writing. These fonts may have a decorative appearance, but they can be difficult to read at small sizes, so they are generally used sparingly.

  • Fantasy

    Fonts that may contain symbols or other decorative properties, but still represent the specified character.

Since Arial is a sans-serif font, therefore a non-fixed width font ( like monospace ), when applied to body with child elements displaying inline-block(without fix for the gaps) it will create space between the child elements.

Although if you apply the font-family to the child elements, like I DID in my 2ND SNIPPET it doesn't happen anymore.


one comment of an article:

The gap between inline elements is, as you suggest, a space character. The width depends on the font (family, variant, etc.) and approximates to .25em

you can check it here

the full article is below

ARTICLE

dippas
  • 58,591
  • 15
  • 114
  • 126
  • The question is why adding `font-family` to `body` affects the space between the buttons? You didn't answer the question. – Misha Moroshko Oct 18 '14 at 04:16
  • I gave you 2 snippets, both with same result, one with a fix for inline-block, another one with your CODE adding font-family:Arial, So I don't see how font-family:Arial is influencing your outcome.. in your code sample you have a typo tough , you wrote body {font-family: Arial;;} instead body {font-family: Arial;}. – dippas Oct 18 '14 at 04:22
4

DEMO

The problem is that there are hidden spaces (a line break and a few tabs counts as a space, just to be clear) between tags. Minimize the HTML or comment the spaces out and everything will work correct:

body {
  font-family: Arial;
}

.my-class {
  display: inline-block;
  margin-left: -4px;
  border: 1px solid #cccccc;
  padding: 20px;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div>
    <button class="my-class">Hello</button><!--
    --><button class="my-class">Stack</button><!--
    --><button class="my-class">Overflow</button>
  </div>
</body>
</html>
IUnknown
  • 335
  • 1
  • 11
Karlen Kishmiryan
  • 7,322
  • 5
  • 35
  • 45
  • 1
    This doesn't answer the question why adding `font-family` to `body` causing the space between the buttons. – Misha Moroshko Oct 15 '14 at 08:41
  • 1
    However this solves the problem and highlights the issue (spaces). – Karlen Kishmiryan Oct 15 '14 at 08:53
  • @MishaMoroshko, that is because the buttons have likely a different spacing (e.g. a tab instead of four spaces on the first button), and their width is different depending on what font has been selected. That's why, if you remove the spaces, font is no longer an issue. You should be able to check by using a monospaced font and `white-space: pre` mode. – LSerni Oct 24 '14 at 13:50
4

Check the demo and use this CSS. If you have not satisfied, just change the font size. It will get fixed.

body {
  font-family: Arial;
  font-size: 15px;
  
}

.my-class {
  display: inline-block;
  margin: 0 0 0 -4px;
  background-color: ccc;
  border: 1px solid #ccc;
  padding: 20px;
}
<div>
    <button class="my-class">Hello</button>
    <button class="my-class">Stack</button>
    <button class="my-class">Overflow</button>
  </div>

See also JSfiddle.

Alexander
  • 4,420
  • 7
  • 27
  • 42
vas_bar_code
  • 213
  • 1
  • 19
3

I recommend to use

float:left

or

float:right  

instead

 display:inline-block; 
Victor Sitnic
  • 380
  • 2
  • 6
-1
use the below css for this: 

.my-class {
  display: inline-block;
  margin-left: -4px;
  border: 1px solid #cccccc;
  padding: 20px;
  margin-right:-1px;
}
DevExpert
  • 22
  • 2
  • It's taking margin from right. So please use margin-right:-1px or 0px; – DevExpert Oct 15 '14 at 06:35
  • I have checked it through the Playground Here Code and it's working. – DevExpert Oct 15 '14 at 09:09
  • body { font-family: Arial; //font-size: 13px; } .my-class { display: inline-block; margin: 0 -1px 0 -4px; background-color: transparent; border: 1px solid #ccc; padding: 20px; } – DevExpert Oct 15 '14 at 09:09