Two boxes styled with display: inline-block sit side by side, but a few pixels of space appear between them even though both have margin: 0. In CSS, where does that gap come from and how do you remove it?
answer
- it is not a margin
- source whitespace becomes a character
- white-space: normal collapses runs
- gap scales with parent font-size
- flex items ignore whitespace-only text
basics
~20 sThe gap is the whitespace between the two tags in the source. Inline-level boxes sit in an inline formatting context, so a newline or space collapses into one rendered space character sized by the parent's font. Remove the whitespace or stop using inline layout.
solid answer
~60 sIt is not a margin — it is a text character. `inline-block` boxes are inline-level on the outside, so they are placed into line boxes alongside text, and the newline and indentation between the two tags in your source is whitespace inside that inline formatting context. Under the default `white-space: normal`, a run of whitespace collapses to a single space, and that space is rendered at the parent's `font-family` and `font-size` — roughly a quarter of an em, which is why it looks like about four pixels at a 16px root. The tell is that the gap scales when you change the parent's font size, and DevTools shows no margin anywhere. The clean fix is to stop using inline layout for a row of boxes: make the parent `display: flex` or `display: grid`, where whitespace-only text between items is not rendered at all. If you must keep `inline-block`, remove the whitespace from the markup, or set `font-size: 0` on the parent and restore a real font size on the children.
code
html · 27 lines<style>
.inline-row > .box {
display: inline-block;
width: 80px;
height: 40px;
margin: 0;
background: #cfd8dc;
}
.flex-row {
display: flex;
}
.flex-row > .box {
width: 80px;
height: 40px;
background: #b0bec5;
}
</style>
<div class="inline-row">
<div class="box"></div>
<div class="box"></div>
</div>
<div class="flex-row">
<div class="box"></div>
<div class="box"></div>
</div>go deeper
Recognise the symptom and name the cause out loud: the space between the tags in the HTML is rendered as a character. Knowing one working fix is enough at this level.
Explain the mechanism precisely — inline-level boxes join an inline formatting context, white-space: normal collapses the run to one space, and its width is one space in the parent's font. Then give the fix and its tradeoff.
Demonstrate the diagnosis rather than the trivia: check computed margins, scale the parent font size to confirm, and argue for restructuring to a flex or grid container so the layout stops depending on source formatting.
Frame it as a fragility class: layout that changes when a formatter reflows markup is a defect waiting to happen. Set the team convention that rows of boxes use a flex or grid container with gap, not inline-level boxes.
## The gap is a character, not a box property When a box is `display: inline-block`, its **outer** display type is inline. That means it does not get stacked as a block; it is placed into a **line box** in the parent's *inline formatting context*, exactly like a word. Anything else in that context is also laid out as inline content — including the text nodes made of the newline and spaces you wrote between the two tags. Under the initial value `white-space: normal`, the browser **collapses** a run of whitespace (spaces, tabs, newlines) into a single space character and renders it. That single space is a real glyph advance, measured in the parent's font at the parent's `font-size`. In most fonts a space is roughly `0.25em`, so at a 16px font size the gap is about 4px — but it is font-dependent, and it changes if the font or size changes. Anyone who insists "the inline-block gap is 4px" has memorised one measurement rather than the mechanism. ## How to confirm the diagnosis in ten seconds Three checks distinguish it from a real margin: - Inspect both boxes: computed `margin-right` and `margin-left` are `0`. - Set `font-size: 40px` on the **parent**. If the gap grows proportionally, it is a rendered space. - Put the two tags on one line with no space between them. If the gap disappears, the source whitespace was the cause. ## The fixes, best first **1. Do not use inline layout for a row.** A flex or grid container does not render whitespace-only text between its children: such text does not generate an anonymous flex or grid item at all. The children are also blockified, so they no longer sit on a baseline or care about source formatting, and you get real control of the spacing with `gap`. ```css .row { display: flex; gap: 0.5rem; /* real, explicit spacing */ } ``` **2. Remove the whitespace from the source.** This keeps `inline-block` but removes the text node. All of these work and all of them are ugly in different ways: putting the tags on one line with no space; ending a line with the opening `<` of the next tag; or placing an HTML comment where the whitespace was so no character remains between the closing and opening tags. It is fragile because it makes the rendered layout depend on how someone formats the markup — which any formatter is free to change. **3. `font-size: 0` on the parent, restored on the children.** A space rendered at zero font size has zero advance, so the gap vanishes. ```css .row { font-size: 0; /* kills the rendered space */ } .row > * { font-size: 1rem; /* children need their own size back */ } ``` The cost is real: every child now inherits `0`, so any child that relies on inherited sizing, or on `em` units resolved against the parent, breaks silently. It also means a text node accidentally left in the parent becomes invisible rather than misplaced, which is a nasty class of bug. **4. Negative margins.** `margin-right: -0.25em` cancels the space, but only for the exact font and size the value was tuned to. It breaks under a font swap, a size change or a different platform's fallback font, and it makes the stylesheet lie about the real spacing. Treat this as a last resort in code you cannot restructure. ## What does not fix it `white-space: nowrap` prevents line breaking but does not remove the collapsed space — the boxes stay on one line *with* the gap. Setting `padding: 0` or `border: 0` changes nothing, because the space is outside both boxes. Floating the boxes does remove the gap, since floats leave the inline flow, but that trades a spacing problem for the containment problems floats bring. ## The wider lesson The gap is the clearest everyday symptom of a general rule: **inline-level boxes are text**. They collapse whitespace like text, sit on the baseline like text, respond to `text-align` on the parent like text, and are affected by `word-spacing` and `letter-spacing` like text. Once a row of boxes is genuinely a layout rather than a sentence, moving the parent to a flex or grid formatting context removes an entire family of surprises at once, of which this gap is only the most famous.
- Why does font-size: 0 on the parent fix it, and what does that break?A collapsed space is rendered in the parent's font at the parent's size, so at `font-size: 0` its advance width is zero. The cost is that every child inherits `0` and must be given a size back explicitly, and any `em`-based value on a child now resolves against zero. It is a fix that silently punishes anyone who later adds a child.
- Does the same gap appear between flex items?No. Whitespace-only text between flex items does not generate an anonymous flex item, so it is never rendered. The same is true of grid items. That is why moving the parent to `display: flex` or `display: grid` and using `gap` is the fix that survives markup reformatting.
saying these in an interview costs you the question
- Blames a default margin the elements do not have
- Insists the gap is always exactly 4px
- Reaches for negative margins tuned to one font
- Thinks white-space: nowrap removes the space
- Calls it a browser bug rather than specified behaviour