Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3 inline-block divs with exactly 33% width not fitting in parent

This is a common problem but I can't figure out why it happens.

I have a parent div and inside that div I have 3 divs with width set to 33% (exactly, not 33.3%!) and display: inline-block.

In Chrome it works well, but in Mozilla and Opera it does not (I didn't test it in IE yet). I thought the problem might be in the algorithm browsers use to calculate pixel sizing from percentages. But when I checked the DOM metrics, I found that the parent's width is 864px and the child's is 285px (that's correct: 864 * .33 = 285.12). But why doesn't it fit in the parent? 285 * 3 = 855, that's 9px less than parent's width!

Oh, yes, padding, margin and border for all divs set to 0 and DOM metrics confirm that.

like image 465
Roman Bekkiev Avatar asked Mar 27 '13 06:03

Roman Bekkiev


People also ask

How do I make DIVS always fit in my parent div?

Method 1: First method is to simply assign 100% width and 100% height to the child div so that it will take all available space of the parent div. Consider this HTML for demonstration: HTML.

How do inline-block elements add up to 100 width?

If you have a border or padding set for your divs, then you've created additional pixels that will prevent your divs from adding up to a 100% width. To fix this, make sure you've added box-sizing: border-box to the div's styles.

How do I increase the width of an inline-block?

Inline elements are built for text and thus they should flow inline with the text, and only be as wide as the text they contain. Thus, you can't set the width of an inline element. Block elements are made to fill all the available width by default and are thus on their own line rather than flowing inline.

How do you make a child DIV element wider than the parent DIV?

In this case, we set the child element's width to be 100% of the viewport width by using a percentage viewport unit (vw), then, we move it to the left side (by the distance of the viewport's half, minus 50% of the width of the parent element) with the left property.


3 Answers

Whitespace in the HTML source code

In the HTML source code, When you have lines of text or images, or elements that are inline-block, if there is any whitespace between them (blank spaces, tabs, or new lines), a single blank space character will be added between them when the page is rendered. For example, in the following HTML, a blank space will appear between each of the four pieces of content:

one
two
<img src="three.png"/>
<span style="display: inline-block;">four<span>

This is very helpful for lines of text, and for small images or HTML elements that appear inside a line of text. But it becomes a problem when inline-block is used for layout purposes, rather than as way to add content inside a paragraph of text.

Removing the extra space

The safest, cross-browser way to avoid the extra 4px or so of space that's added between inline-block elements, is to remove any whitespace in the HTML source code between the HTML tags.

For instance, if you have a ul with 3 floated li tags:

<-- No space, tabs, or line breaks between </li> and <li> -->
<ul>
    <li>...</li><li>...</li><li>...</li>   
</ul>

Unfortunately, this hurts the maintainability of the website. Besides making the code unreadable, it severely compromises the separation of data and formatting.

If another programmer comes along later and decides to put each li tag on a separate line in the source code (unaware of why the tags were on the same line, or possibly running it through HTML Tidy and not even having a chance to notice any related HTML comments), suddenly the website has a formatting bug that may be difficult to identify.

Consider floating elements instead

The whitespace behavior strongly suggests that it may be inappropriate to use inline-block for general-layout purposes, to use it for anything other than adding content inside the flow of a paragraph of text.

Plus, in some cases inline-block content is very difficult to fully style and align, especially on older browsers.

Quick summary of other solutions

  1. Put the close tag on the same line as the next open tag, with no white space between them.
  2. Use HTML comments to fill all of the whitespace between the close tag and the next open tag (as @Arbel suggested).
  3. Add a negative left margin to each element (usually -3px or -4px, based on the font-size). I don't recommend this particular approach.
  4. Set the font-size for the container element to 0 or 0.01em. This doesn't work in Safari 5 (not sure about later versions), and it may interfere with Responsive Design websites, or any website that uses a font-size unit other than px.
  5. Remove whitespace-only text nodes from the container using JavaScript or jQuery. This doesn't work in IE8 and earlier, as text nodes are not created in those browsers when there's only whitespace between elements, though space is still added between the elements.
  6. Set letter-spacing and word-spacing for the container (as @PhillipWills suggested). Further info. This requires standardizing em sizes on the website, which may not be a reasonable option for all websites.
  7. Add text-space-collapse: discard; to the container (previously called white-space-collapse). Unfortunately, this CSS3 style is not yet supported by any browsers, and the standard hasn't been fully defined.
like image 67
12 revs Avatar answered Sep 21 '22 10:09

12 revs


If you don't want to mess up the HTML formatting e.g. having all the elements with inline-block written in one line for future readability and also get rid of the extra white space that is added between them, you can "comment" the white space.

For example in your code this will solve the problem, it will even work with 33.3% instead of 33%:

.parent {
    width: 100%;
 }
.child{
    display: inline-block;
    width: 33.3%;
}

/\

<div class="parent">
       <div class="child">bla-bla1</div><!-- 
    --><div class="child">bla-bla2</div><!-- 
    --><div class="child">bla-bla3</div>
</div>
like image 32
Arbel Avatar answered Sep 18 '22 10:09

Arbel


A space is added between the inner divs. There is some CSS voodoo to correct this problem:

div {
    letter-spacing: -.31em;
    word-spacing: -.43em;
}
div div {
    letter-spacing: normal;
    word-spacing: normal;
}

Of course, you'll probably prefer to use classes or something to differentiate between parent and children.

like image 21
philwills Avatar answered Sep 19 '22 10:09

philwills