Why does an inline-block align to top if it has no content?
The baseline of an inline-block that has no inline children, including text, is its bottom margin edge (or simply bottom edge if it has no bottom margin). This baseline is then aligned with the baselines of the rest of the text. This is mentioned at the very end of section 10 of the spec.
Why does this inline-block element have content that is not vertically aligned
The default vertical-align
value is baseline
which
Aligns the baseline of the box with the baseline of the parent box
Note: You can see this default value in action by adding vertical-align:baseline
to your .divAccountData
selector. Since baseline
is default the alignment is unchanged.
You need to change it to top
to align the blocks at the top, for example:
.divAccountData {
display: inline-block;
background: red;
width: 400px;
height: 40px;
vertical-align: top;
}
Baseline is defined as
the line upon which most letters "sit" and below which descenders extend
To address why adding text seems to fix the problem it is because
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.
from CSS2 Visual formatting model details
So adding just a single character changes the baseline, causing the second block to appear at the same vertical alignment. This only works if both blocks contain the same number of lines. Try adding more words to one of your blocks and you will see that without forcing vertical-align:top
on the second block it will move depending on how many lines of text exist in the first block.
Edit: Found a related question Why is this inline-block element pushed downward?
Why my inline-block divs are not aligned when only one of them has text?
This is the consequence of the "baseline" vertical alignment in CSS. From the CSS 2.1 spec, section 10.8 Line height calculations: the 'line-height' and 'vertical-align' properties
baseline
Align the baseline of the box with the baseline of the parent box. If the box
does not have a baseline, align the bottom margin edge with the parent's baseline. (my emphasis)
Because the default alignment for the inline-blocks is "baseline", unless it is overridden, this rule applies. When text is put in the inline-block, that text will create a baseline for the inline-block and the first (non-bolded) sentence applies.
When there is no text in the inline-block, then it has no baseline and so the second (bolded) sentence applies.
In the JSFiddle here: http://jsfiddle.net/WjCb9/1/ I have removed from your example the margin:1em
which was creating (at least for me) a misleading illusion, and added the text baseline
to show where the baseline of the containing box is. The baseline is along the bottom of the word "baseline", so you can see that the empty inline-block has its bottom margin edge aligned with the parent's baseline as required by the CSS rule above.
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.
- Set first div overflow:visible (or remove it altogether).
- Set second div overflow: other than visible.
- Set both divs overflow: other than visible.
Now bring back your clutter and see if everything is looking to fine to you.
- Bring back your floated div (of course there is need to
increase some width of body)
You see it has no effect. - Bring back same odd margins.
- 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)
- Now remove additional characters I added to aid in
understanding. (and of course remove negative left) - 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.
Vertical align not working on inline-block
It doesn't work because vertical-align
sets the alignment of inline-level contents with respect to their line box, not their containing block:
This property affects the vertical positioning inside a line box of
the boxes generated by an inline-level element.
A line box is
The rectangular area that contains the boxes that form a line
When you see some text which has multiple lines, each one is a line box. For example, if you have
p { border: 3px solid; width: 350px; height: 200px; line-height: 28px; padding: 15px; }
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.</p>
My inline-block elements are not lining up properly
10.8 Line height calculations: the 'line-height' and 'vertical-align' properties
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.
This is a common issue involving inline-block
elements. In this case, the default value of the vertical-align
property is baseline
. If you change the value to top
, it will behave as expected.
Updated Example
.position-data {
vertical-align: top;
}
Why is content of the inline-block affects its position in the container
You are using display:inline-block
, so the buttons are aligned by their vertical-align
property, which defaults to baseline
.
This is a diagram from the specs which illustrates exactly that:
You can see in the first two boxes how padding and the font size of the content influence the positioning.
As a fix, use vertical-align: top
or bottom
, or even middle
.
Edit: The image is from the table section and the situation is slighty different for inline-blocks.
Related Topics
Play Infinitely Looping Video On-Load in HTML5
Flexbox on Ie11: Image Stretched for No Reason
Display:Inline with Margin, Padding, Width, Height
Aligning Elements Left and Center with Flexbox
Placing a <Div> Within a <Canvas>
How to Preload a Page Using HTML5
Html5 Placeholder Disappears on Focus
Absolute Position and Overflow:Hidden
It Is Possible to Expand a Textarea Only with CSS
Do HTML5 Script Tag Need Type="Javascript"
How to Disable the Spell Checker on Text Inputs on the Iphone
Changing the Text Selection Color Using CSS
HTML Generated Microsoft Word Document with Header, Footer and Watermark
How to Have Images in Line with Text in CSS
Is There a CSS Selector for Selecting an Element Futherup in the HTML
What Is an Srcset Attribute in Img Tag and How to Use It
Override Overflow:Hidden with Z-Index
Why Alignment Mark List Is Different on Webkit When Using :Before Height