Inline-Block Boxes Not Fitting in Their Container

inline-block boxes not fitting in their container

The problem is that inline-block elements are, by default, rendered with a bit of extra space.

Why? Because a div set to inline-block has some inline element characteristics.

A space or line break between span elements will result in a space rendered by the browser.

Similarly, if you're writing text in a <p> element, every time you hit the space bar or add a line break a space will be rendered by the browser.

This same rule applies to inline-block divs. A space or line break in the source will result in a space rendered. This creates unexpected width, which can result in an overflow or wrapping.

One solution is to remove all whitespace between elements in the source:

.ok {  width: 300px;  background: red;  height: 100px;  box-sizing: border-box;}.box {  display: inline-block;  box-sizing: border-box;  width: 25%;  border: 2px solid blue;  height: 100%;}
<div class="ok"><div class="box">1</div><div class="box">2</div><div class="box">3</div><div class="box">4</div></div>

Why do inline-block elements not fit properly within container?

Inline elements include the extra whitespace that exists in the markup, as well as descender height for letters like g, j, p, q, y. This extra white space makes the elements larger than you expect them to be.

Though there are workarounds to continue using inline-block I would recommend using flexbox or float them if you cannot use flexbox.

Flexbox Solution

* {   box-sizing: border-box;}#playerChoice {  display: flex;  width: 560px;  height: 80px;  border: 1px dashed indianred;}
.choice { flex-grow: 1; border: 1px dashed #ccc;}
<div id="playerChoice">  <div class="choice" id="choice1">1</div>  <div class="choice" id="choice2">2</div>  <div class="choice" id="choice3">3</div>  <div class="choice" id="choice4">4</div>  <div class="choice" id="choice5">5</div>  <div class="choice" id="choice6">6</div>  <div class="choice" id="choice7">7</div></div>

Why do these inline-block divs not fit inside their container?

The space between the elements cause extra width. You need to put all your elements on one line, like this:

<div flex=1 style="...">This is the A Bo</div><div ...>This is the B Box</div>...

Why don't containers expand to fit their inline elements

The reason is explained in the Visual Formatting model documentation (emphasis mine):

In an inline formatting context, boxes are laid out horizontally, one
after the other, beginning at the top of a containing block.
Horizontal margins, borders, and padding are respected between these
boxes. The boxes may be aligned vertically in different ways: their
bottoms or tops may be aligned, or the baselines of text within them
may be aligned. The rectangular area that contains the boxes that form
a line is called a line box.

The width of a line box is determined by a containing block and the
presence of floats. The height of a line box is determined by the
rules given in the section on line height calculations
.

The line height is then calculated as:

The height of a line box is determined as follows:

  1. The height of each inline-level box in the line box is calculated. For
    replaced elements, inline-block elements, and inline-table elements,
    this is the height of their margin box; for inline boxes, this is
    their 'line-height'. (See "Calculating heights and margins" and the
    height of inline boxes in "Leading and half-leading".)
  2. The
    inline-level boxes are aligned vertically according to their
    'vertical-align' property. In case they are aligned 'top' or 'bottom',
    they must be aligned so as to minimize the line box height. If such
    boxes are tall enough, there are multiple solutions and CSS 2.1 does
    not define the position of the line box's baseline.
  3. The line box height is the distance between
    the uppermost box top and the lowermost box bottom. Empty inline elements
    generate empty inline boxes, but these boxes still have margins,
    padding, borders and a line height, and thus influence these
    calculations just like elements with content.

And as MDN notes about the box model:

Note that, for non-replaced inline elements, the amount of space taken
up (the contribution to the height of the line) is determined by the
line-height property, even though the border and padding appear
visually around the content.

and reiterated by the W3 for inline non-replaced elements:

The 'height' property doesn't apply, but the height of the box is
given by the 'line-height' property.

https://www.w3.org/TR/REC-CSS2/visudet.html#q15

Where the line height is "the height that is used to calculate line box height." So while padding or borders might give the look of height to an inline element, only the line-height property will affect parent nodes. As you can see in the example below, the line height on the spans is affecting the height of the parent div.

button,div {  background: blue;}
span { background: orange; line-height: 10em;}
hr { margin: 100px;}
<div>  <span class="btn__content">        I'm div inline content    </span></div>
<hr>
<button class="btn" type="button"> <span> I'm button inline content </span></button>

CSS when inline-block elements line-break, parent wrapper does not fit new width

You can't. By default, inline-block elements have a shrink-to-fit width:

The shrink-to-fit width is:

min(max(preferred minimum width, available width), preferred width).

Then,

  • When preferred minimum width <= preferred width <= available width, the width will be the preferred width, as you desire.
  • When available width <= preferred minimum width <= preferred width, the width will be the preferred minimum width, as you desire.
  • When preferred minimum width <= available width <= preferred width, the width will be the available width, even if you don't like it.

If you really don't want this, I guess you could add a resize event listener with JS, and set the desired width manually.

Container inline-block once again

If you don't mind using flexbox.

.container {  border: 10px solid red;  display: flex;  box-sizing: border-box;}
.container > div { flex-basis: 50%; border: 10px solid blue; margin: 10px; padding: 10px;}
.left img { width: 100%; height: 100%;}
.right__content { display: flex; flex-direction: column; justify-content: center; height: 100%;}
.right__content * { margin: 0;}
<div class="container">  <div class="left">      <img src="https://placehold.it/300x150" alt="left img">  </div>  <div class="right">     <div class="right__content">       <h1>Header text</h1>       <p>my desc</p>     </div>  </div></div>

Do Inline elements establish a Line Box for their content?

Your heading and first paragraph ask two different questions:

  • Do Inline elements establish a Line Box for their content?
  • [Are] line boxes are formed inside inline-level elements?

They have different answers, "No", and "Sometimes" respectively, so the first thing that needs to be dealt with is the -level suffix.

An inline-level box is a broader category than an inline box. A span element which contains only text generates, by default, a sequence of inline boxes sufficient to lay out that text content over as many lines as is necessary. All inline boxes are also inline-level boxes, but the opposite is not true. Elements whose computed display is inline-block, inline-table, inline-flex and inline-grid all generate boxes that are inline-level, but are not inline boxes.

Similar applies to block versus block-level. Block-level describes how a box lays out relative to its parents and siblings. Block containers are boxes in which their child boxes are laid out either as sequence of block-level boxes, or within a stack of line boxes, and never as a mixture of both.

Elements whose computed display value is block, flow-root and list-item and are being laid out in a block formatting context (i.e. they're not a flex item or a grid item) generate a single box that is both block-level and a block container. These are called block boxes.

But boxes generated for elements that have computed display values of table, flex, and grid are block-level, but they are not block containers. Their descendants are laid out using different rules. These are not block boxes.

Conversely, elements that have computed display values of inline-block and table-cell generate boxes that are block containers but they are not block-level. They interact with their parents and siblings differently than block level boxes do.

So, specifically, inline-block boxes, which are inline-level, contain either a sequence of block-level boxes, or a stack of line boxes in which other inline-level boxes are laid out.


Now, an inline box can contain other inline-level boxes, but that does not make it a block container, even if one of those inline-level boxes is itself a block container. The block container of the inline box and all its descendant inline-level boxes that are not themselves inside other formatting contexts is the nearest ancestor that is a block container.

So, suppose we have this tree of boxes

 display:block                     block level, block container
| ↑ ↑
+ - display:inline inline level ---------+ | \
| | |- In the same line box
+ - display:inline-block inline level, block container /
| ↑
+ some text anonymous inline box --+ in a line box

where the arrows point from inline-level boxes to their block container.



Related Topics



Leave a reply



Submit