Why Do 'Inline-Block' Elements Auto-Clear Their Children

Why do `inline-block` elements auto-clear their children?

Inline-block elements establish new block formatting contexts for their contents. A block formatting context root always tries to contain its floats if sized automatically; see section 10.6.7 of the spec:

In addition, if the element has any floating descendants whose bottom margin edge is below the element's bottom content edge, then the height is increased to include those edges.

This is what makes an inline block able to contain its floats; no clearance is actually involved since no clearing element is introduced after the floating children.

Why does inline-block automatically adjust its width according to it's child's width?

display: inline-block is basically a sweet-spot between display: inline; (which is default for span, strong, em, etc.) and display: block; (which is default for div, p, etc).

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. This is good for things like paragraphs, but sometimes you want shorter lines so it is possible to adjust the width for block elements.

Inline-block elements are in the middle. They flow inline like display: inline; elements, but you can set the width like display: block; elements.

child div are coming below each other even after using inline-block

It's is flowing as display:block even through I have given display:inline-block.

There are a couple of things you can do.
Either float each element, you want on the same line, to the left or add display:inline-block;.

Just noticed that you have given display:inline-block; to the parent element not to the child elements. This is why it wasn't working for you.

Float left:
https://jsfiddle.net/25brcg9x/1/

Display inline-block:
https://jsfiddle.net/beekvang/25brcg9x/2/

How to stop Inline-block from taking up more width than child elements

Whenever the contents of an inline-block wrap, even once, it will take up the entire available width.

As for the desired behavior, I suppose you are looking for this: ...?

* {  box-sizing: border-box;}body {  background-color: red;  text-align: center;}main {  display: inline-block;  margin: 5vw;  background-color: skyblue;  text-align: left;  padding: .8rem;  overflow: hidden;}main p {  margin: 0;  padding: 10px;  color: #bbb;  font-size: 0.9rem;}a {  color: #fff;  text-decoration: none;}a[href="#"] {  display: inline-block;  width: calc(33.3333% - 1.6rem);  margin: .8rem;  background-color: #f1f1f1;  vertical-align: top;  box-sizing: border-box;  float: left;}img {  max-width:100%;}
<link href="https://necolas.github.io/normalize.css/latest/normalize.css" rel="stylesheet"/><main> <!-- skyblue -->        <a href="#">          <div><img src="http://i.imgur.com/7WBWShL.jpg" alt="Sample Image"></div>          <p>mmm random text caption.</p>        </a>        <a href="#">          <div><img src="http://i.imgur.com/7WBWShL.jpg" alt="Sample Image"></div>          <p>Is that a sheep or a goat?</p>        </a>        <a href="#">          <div><img src="http://i.imgur.com/7WBWShL.jpg" alt="Sample Image"></div>          <p>A ram maybe? Is that wood tiling behind it?</p>        </a>        <a href="#">          <div><img src="http://i.imgur.com/7WBWShL.jpg" alt="Sample Image"></div>          <p>Definitly an animal on grass...on wood</p>        </a>        <a href="#">          <div><img src="http://i.imgur.com/7WBWShL.jpg" alt="Sample Image"></div>          <p>Umm. k.</p>        </a>    </main>

Why does setting overflow alter layout of child elements?

Overflow of anything but visible creates a new block formatting context which causes floats to be contained. It's standard behaviour.

Floats, absolutely positioned
elements, inline-blocks, table-cells,
table-captions, and elements with
'overflow' other than 'visible'
(except when that value has been
propagated to the viewport) establish
new block formatting contexts.

In a block formatting context, boxes
are laid out one after the other,
vertically, beginning at the top of a
containing block. The vertical
distance between two sibling boxes is
determined by the 'margin' properties.
Vertical margins between adjacent
block boxes in a block formatting
context collapse.

In a block formatting context, each
box's left outer edge touches the left
edge of the containing block (for
right-to-left formatting, right edges
touch). This is true even in the
presence of floats (although a box's
line boxes may shrink due to the
floats), unless the box establishes a
new block formatting context (in which
case the box itself may become
narrower due to the floats).

How to make an inline-block parent's width be wrapped around it's children?

This is caused by not clearing the floats and as far as I've been able to read, there's no direct solution to do this in a fully responsive way without using JavaScript.

But with fixed dimensions, there is an approach that will clear the floats and wrap the parent :

http://jsfiddle.net/cfL491Lc/

@media screen and (max-width: 555px) {
div > div:last-child {
clear: left;
}
}

With the following logic : breakpoint = width of divs + padding + margin on body + 19px scrollbar.

If there's no scrollbar present, it will wrap a bit too early but that's the limitation of media queries. Depending on the surrounding content (especially the total height) another query might be necessary.

Why is this inline-block element pushed downward?

Basically you have added more clutter in your code which is creating more confusion so first I try to remove clutter which hinders understanding the real issue.

First of all we have to establish that what's the real question?
Its that why "inline-block" element is pushed downward.

Now we start to understand it and remove the clutter first.

1 -
Why not give all three divs same border width?
Let's give it.

2 - Does floating element has any connection with inline-block element being pushed downward?
No, it has nothing to do with it.

So, we have removed that div altogether. And you are witnessing same behavior of inline-block element being pushed downward.

Here comes the turn of some literature to grasp the idea of line boxes and how they are lined in the same line esp read last paragraph carefully because there lies the answer of your question.

The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge.

If you are not sure about baseline then here is brief explanation in simple words.

All characters except 'gjpqy' are written on the baseline you can think of baseline as if you draw a simple horizontal line same as underlining right below these "random characters" then it will be the baseline but now if you write any of 'gjpqy' character(s) on the same line then lower part of these characters would fall below the line.

So, we can say that all characters except 'gjpqy' are written completely above the baseline while some part of these characters are written below the baseline.

3 - Why not check where is the baseline of our line?
I have added few characters which show the baseline of our line.

4 - Why not add some characters in our divs too to find their baselines in the div?
Here, some characters added in divs to clarify baseline.

Now when you understand about baseline, read the following simplified version about baseline of inline-blocks.

i) If inline-block in question has its overflow property set to visible (which is by default so no need to set though).
Then its baseline would be the baseline of the containing block of the line.

ii) If inline-block in question has its overflow property set to OTHER THAN visible.
Then its bottom margin would be on the baseline of the line of containing box.

  • First point in detail

Now look at this again to clarify your concept that what's happening with green div.
If yet any confusion then here is added more characters close to green div to establish the baseline of the containing block and green div baseline is aligned.

Well, I am now claiming that they have same baseline? RIGHT?

5 - Then why not overlap them and see if they are fit right one on another?
So, I bring third div -left: 35px; to check if they have same baseline now?

Now, we have got our first point proved.

  • Second point in detail

Well, after explanation of first point second point is easily digestible and you see that first div which has overflow property set to other than visible (hidden) has its bottom margin on the base line of the line.

Now, you can do couple of experiments to further illustrate it.

  1. Set first div overflow:visible (or remove it altogether).
  2. Set second div overflow: other than visible.
  3. Set both divs overflow: other than visible.

Now bring back your clutter and see if everything is looking to fine to you.

  1. Bring back your floated div (of course there is need to

    increase some width of body)
    You see it has no effect.
  2. Bring back same odd margins.
  3. Set green div to overflow: visible as you set in your question (that misalignment is due to increase of border width from 1px to 5px so if adjust negative left you'll see there is no issue)
  4. Now remove additional characters I added to aid in
    understanding. (and of course remove negative left)
  5. Finally reduce body width because we no longer need wider one.

And now we are back to where we started from.

Hopefully I have answered your question.



Related Topics



Leave a reply



Submit