Why Does Overflow: Hidden Add Additional Height to an Inline-Block Element

overflow:hidden on inline-block adds height to parent

I had this issue when building a horizontal slider. I fixed it with vertical-align:top on my inline-block elements.

ul {
overflow-x: scroll;
overflow-y:hidden;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}

ul&::-webkit-scrollbar {
display: none;
}

li {
display: inline-block;
vertical-align: top;
width: 75px;
padding-right: 20px;
margin:20px 0 0 0;
}

Why does overflow: hidden add additional height to an inline-block element?

The extra height is the same height as the height difference between vertical-align: baseline, and vertical-align: bottom. The "descender line". That's where the seemingly random "5 extra pixels" comes from. If the font size is 10 times as large, this gap will also be 10 times as large.

Also, it seems that when overflow: hidden is not there, the inline-block element has its baseline as the same baseline of its last line of text.

This leads me to believe that overflow: hidden forces the baseline of the entire inline-block element to be at the bottom of the element. Even though there is no text there, the parent of the inline-block element reserves space for the descender line. In the example given in the question, it cannot be easily seen since the parent of the inline-block element has height: 100%. So, instead, that extra space reserved for the descender line overflows out of that parent div.

Why is this space still there, even though there's no text? I think that's because the inline-block creates an inline formatting context, which is what causes this space. Were this element to be a block, it would only create this inline formatting context once it encounters an inline element or text.

This is just a theory, but it seems to explain it. It also explains why @Jonny Synthetic's answer works: adding overflow: hidden to the parent hides that extra descender line.

Thanks to @Hashem Qolami for the jsbins that gave me this theory.

Why baseline of `inline-block` element with `overflow:hidden` is set to its bottom margin?

1. What the reason to change baseline of inline-block element from baseline of its line box to bottom margin edge?

The baseline of an 'inline-block' is changed to its bottom margin edge when its overflow property is set to hidden (full specification here).

As for the reason for this decision, I think since the overflown part is hidden, user agents (browsers) may choose to render that overflown part and not display it, or choose to not render it at all. And when the overflown part is not rendered, user agents have no way to tell the baseline of its last line box, as it is not rendered, where it goes is not known.

If the baseline of 'inline-block' whose overflow is set to hidden is still kept as the baseline of its last line box, user agents are forced to render what is hidden to user, which may hinder performance, or at least, put extra restrictions on user agents. What's more, in such case, other inline texts in the same line box are aligned to such a baseline where texts around the overflow-hidden inline-box is hidden, which is kind of stange and not intuitive.

I made a simple demo emulating that inline-block with overflow hidden still has its baseline set to the baseline of its last line box.

emultaing_imaginary_baseline_of_overflow_hidden_inline_block

var isOverflowHidden = false;document.querySelector('button').onclick = function() {  document.getElementById('inline-box').style.overflow = isOverflowHidden ? '' : 'hidden';  isOverflowHidden = !isOverflowHidden;}
html { background: white; }#inline-box { display: inline-block; height: 18px; }.overflown { color: white; }
<p><button id="toggle">Toggle 'overflow: hidden;' on 'inline-block'</button></p>
<span> texts sit <span id="inline-box"> texts in inline-block <br> <span class="overflown"> line 2 <br> line 3 </span> </span> on baseline</span>

overflow:hidden + display:inline-block moves text upwards

This happens because the inline-block element has height equal to its parent and overflow: hidden causes its bottom edge to be aligned on the text baseline of the parent. As a result the space that is available for descenders on the text is essentially doubled for the <span> (JSFiddle).

You can fix this by also giving it vertical-align: bottom.

Why does inline-block work differently when overflow: hidden is applied?

By default inline boxes in a line are vertically aligned by their baselines (since the default value of the vertical-align property is baseline) and the baseline of inline-blocks depends on the value of the overflow property. If the value of the overflow property on an inline-block is visible, then the baseline of this inline-block is the baseline of its last line, but if the overflow property has another value (for example hidden), then its baseline is the bottom margin edge.

The documentation says

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.

I also suggest you reading this great article in order to understand completely the vertical alignment of inline stuff.

css overflow:hidden with display:inline-block

Answer to your questions as below.

why there is 2px blank between .text element and .bottom element when the .text has overflow:hidden attribute

A > You need to add a vertical-align property to align the elements to see no gaping. Link With Vertical Align

Code

.overflow {
overflow: hidden;
vertical-align: top;

}

PS: You can change vertical-align:top; to any other vertical-align properties as per your needs.

why the .right elment not align with the left when it has overflow:hidden attribute

A > Alignment has nothing to do with overflow. You need to use vertical-alignment to align it as per you want. I also believe, that this has a link to question 1. So if you check the above, it now aligns.

what dose the overflow:hidden really do

This value indicates that the content is clipped and that no scrolling
mechanism should be provided to view the content outside the clipping
region; users will not have access to clipped content. The size and
shape of the clipping region is specified by the 'clip' property.

Source

Hope this helps.

Overflow hidden not working with inline-block parent

From MDN about text-overflow:

This property only affects content that is overflowing a block container element in its inline progression direction.

It means you should apply text-overflow property to the element with display: block to clip its inline content, and also limit the width of the element with display: block.

In your code snippet, you could add max-width to .user-info and overflow: hidden + text-overflow: ellipsis + white-space: nowrap to .user-info-text's child blocks:

.profile__dropdown {    position: absolute;    right: auto;    margin-top: 15px;    top: 30px;    left: 50px;    z-index: 100;    padding-left: 5px;    width: 180px;    padding-top: 5px;    padding-bottom: 5px;    background-color: #fff;    background-clip: padding-box;    border-radius: 4px;    box-shadow: 0 0 60px rgba(0,0,0,0.1);}.avatar {    display: inline-block;    overflow: hidden;    line-height: 1;    vertical-align: middle;    border-radius: 50%;    margin-right: 5px;}.avatar--circle {    height: 30px;    width: 30px;    background: #ddd;}.avatar--md {    height: 45px;    width: 45px;}.user-info>* {    display: inline-block;    vertical-align: middle;}.user-info-text {    padding-left: 4px;    max-width: 100px;    box-sizing: border-box;}.user-info-text>* {    display: block;}.user-info-text>*,.profile__info a, .profile__info span, .profile__info li {    overflow: hidden;    text-overflow: ellipsis;    white-space: nowrap;}.profile__dropdown li {    display: block;    overflow: hidden;    color: #777;    text-overflow: ellipsis;    white-space: nowrap;    text-align: left;    float: initial;}.profile__info a {    padding: 0;    width: 100%;    height: initial;}.profile__detail a {    display: block;    padding: 0 8px;    font-weight: 600;    color: rgba(0,0,0,0.5);    height: 30px;}.profile__wrapper li {    float: left;    position: relative;}.profile__dropdown li.separate {    margin: 4px 0 0 0;    border-top: 1px solid rgba(0,0,0,0.075);}.profile__dropdown li a, .user-info {    padding: 4px 10px 4px 15px;}
<ul class="profile__dropdown">    <li class="user-info">        <div class="avatar avatar--circle avatar--md"></div>        <div class="user-info-text"><span>John Joe adfasdfadfadsf</span><span>0011026184</span></div>    </li>    <li class="separate"><a href="#">Settings adfadfasdfasdfdsfadsf</a></li>    <li><a href="#">Logout</a></li></ul>

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.

can overflow: hidden; work with inline-blocks?

For padding and borders you can use box-sizing: border-box; on your child element.

border-box: "The width and height properties (and min/max properties) includes content, padding and border, but not the margin"

source: box-sizing

I think for margin you need to cut some space off your .children. For example: width: 49.5%; margin: 1%;

Why does these inline-block element produce extra width?

The red portion of the item is an artifact of the browser not knowing how to correctly size the containers. It's using the length of the text to determine the width before the table layout is applied. If you know the width of the items, you can use this simpler approach:

.item {  display: inline-block;  background-color: blue;  width: 120px;}
.image { display: block; height: 120px;}
<div class="item">  <img src='http://i.imgur.com/nV2qBpe.jpg' class="image">  <p class='text'>Some text that may need to wrap into multiple lines</p></div>
<div class="item"> <img src='http://i.imgur.com/nV2qBpe.jpg' class="image"> <p class='text'>Some text that may need to wrap into multiple lines</p></div>
<div class="item"> <img src='http://i.imgur.com/nV2qBpe.jpg' class="image"> <p class='text'>Some text that may need to wrap into multiple lines</p></div>
<div class="item"> <img src='http://i.imgur.com/nV2qBpe.jpg' class="image"> <p class='text'>Some text that may need to wrap into multiple lines</p></div>


Related Topics



Leave a reply



Submit