Why is this inline-block element pushed downward?

2018-12-31 01:39发布

Following is my code and I want to understand that why #firstDiv is being pushed downward by all browsers. I really want to understand the inner workings of the fact that why its being pushed downward rather than pulling it upward by one way or another. (and I know how to align their tops :))

And I know that its overflow:hidden which is causing it but not sure that why its pushing that div downward.

<div id="container">
<div id="firstDiv">FIRST</div>
<div id="secondDiv">SECOND</div>
<div id="thirdDiv">THIRD
<br>some more content<br> some more content
</div>
</div>

body{
    width: 350px;
    margin: 0px auto;
}
#container {
    border: 15px solid orange;   
}
#firstDiv{
    border: 10px solid brown;     
    display:inline-block;
    width: 70px;      
    overflow:hidden;  
}
#secondDiv{
    border: 10px solid skyblue;         
    float:left;
    width: 70px;     
}
#thirdDiv{
    display:inline-block;
    border: 5px solid yellowgreen;    
}

http://jsfiddle.net/WGCyu/.

标签: overflow css
8条回答
牵手、夕阳
2楼-- · 2018-12-31 02:08

Just use vertical-align:top;

Demo

查看更多
浮光初槿花落
3楼-- · 2018-12-31 02:18

I originally started on answering this question, but it was locked as dupe before I could finish, so I post the answer here instead.

First, we need to understand what inline-block is.
The definition in MDN says:

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)

To understand what's going on here, we need to look at vertical-align, and it's default value baseline.

vertical position visualizations
In this illustration you have this color chart:
Blue: The baseline
Red: The top and bottom of the line-height
Green: The top and bottom of the inline content box.

In the #left element, you do have some textual content that controls what is the baseline. This means that the text inside defines the baseline for #left.
In the #right, there is no content, so the browser has no other option than to use the box bottom as the baseline.

Se this visualisation where I have drawn the baseline on an example where the first inline container has some text, and the next is empty:

Baseline drawn

If you specifically align one element to top, you really say that you align the top of this element to the top of of the line box.

This might be easier to understand by an example.

div {
    display: inline-block;
    width: 100px;
    height: 150px;
    background: gray;
    vertical-align: baseline;
}
div#middle {
    vertical-align: top;
    height: 50px
}
   
div#right {
    font-size: 30px;
    height: 100px
}
<div id="left">
  <span>groovy</span>
</div>
<div id="middle">groovy</div>

<div id="right">groovy</div>

The result is this - and I added the blue baseline, and the red line box: Explained vertical-align
What happens here, is that the height of line box is depended on how the the content of the entire line is laid out. This means that to calculate the top alignment, the basline alignments must be calculated first. The #middle element has vertical-align:top, so this is not used for the baseline positioning. but the #left and #right are positioned vertically so that their baselines are aligned. When this is done, the height of the line box has increased, because the #right element has been pushed up a bit as a result of the larger font size. Then the top position for the #middle element can be calculated, and this is along the top of the line box.

查看更多
忆尘夕之涩
4楼-- · 2018-12-31 02:20

The default value for vertical-align in CSS is baseline & this rule is also apply with inline-block read this http://www.brunildo.org/test/inline-block.html

Write vertical-align:top in your inline-block DIV.

Check this http://jsfiddle.net/WGCyu/1/

查看更多
时光乱了年华
5楼-- · 2018-12-31 02:20

Try adding padding:0; to the body and removing the margin of your divs.

Add background-color:*any color aside from background* to check the difference.

查看更多
与风俱净
6楼-- · 2018-12-31 02:21

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.

查看更多
何处买醉
7楼-- · 2018-12-31 02:23

Try making all CSS properties of all Elements same.

I had similar problem and while fixing this I identified that I was dropping an Element with Font property into Div Element.

After dropping that Element with Font property the alignment of all DIV was disturbed. To fix this I set Font property to all DIV elements the same as the element that is dropped into it.

In the following example, the Dropped element of class ".dldCuboidButton" defined with font-size:30 px.

So I added same property to remaining classes i.e. .cuboidRecycle, .liCollect , .dldCollect which are used by DIV elements. In that way all DIV element follow the same Measurments before and after dropping the element into it.

.cuboidRecycle {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.liCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#cab287;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}

.dldCollect {
    height:40px; 
    width:'20px; float:right';
    overflow:'none';
    background-color:#009933;
    color:#ffffff; 
    border-radius:8px; 
    text-align:'center'; 
    vertical-align:'top';
    display: inline-block;
    font-size: 30px; /* Set a font-size */
}


.dldCuboidButton {
    background-color:  #7c6436;
    color: white; /* White text */
    font-size: 30px; /* Set a font-size */
    border-radius: 8px;
    margin-top: 1px;
  }

Here is the example of HTML dynamically created using above CSS.

$("div#tabs").append(
  "<div id='" + newTabId + "'>#" + uniqueId + 
  "<input type=hidden id=hdn_tmsource_" + uniqueId + "  value='" + divTmpfest + "'>" + 
  "<input type=hidden id=leCuboidInfo_" + uniqueId + " value=''>" + 
  "<div id='" + divRecycleCuboid + "' class=cuboidRecycle ondrop='removeDraggedCuboids(event, ui)'  ondragover='allowDrop(event)'><font size='1' color='red'> Trash bin </font></div>" +
  "<div id='" + divDropLeCuboid  + "' class=liCollect ondrop='dropForLinkExport(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Manifest Cuboid here</font></div>" +
  "<div id='" + divDropDwldCuboid  + "' class=dldCollect ondrop='dropForTMEntry(event)'  ondragover='allowDrop(event)'><font size='1' color='red'>Drop Template Cuboids here..</font></div>" +
  "</div>" 
);
查看更多
登录 后发表回答