4

I'm aware that when an inline-block element has an overflow property whose computed value is different than visible, its baseline is the bottom margin edge.

See this in practice in this fiddle by clicking the toggle button to add overflow:hidden to the div element. The div's baseline will align with its bottom edge, generating some whitespace/margin below it.

This behavior is well explained in this answer.

My question is, how do I "fix" it so that margin does not appear when the element receives overflow:hidden?

The logical fix I can think of is to change the div's vertical-align (which defaults to baseline) to something else. But I'm having trouble deciding which vertical-align is the most appropriate:

  • top seems currently bugged in Chrome 33, all direct children of the element (text nodes and inline-block/replaced content) are aligned to the top edge of the div.

  • bottom would be another option, but the div then moves slightly up/down while animating its height/vertical padding with jQuery.

  • middle seems to work fine as far as I've tested, but I'm not sure how the resulting alignment is calculated by the browser then.

I've also discovered other hacks, such as applying line-height:0 or font-size:1px in the parent and wrapping all the children in a container which resets its line-height/font-size, but those are terribly ugly hacks.

What would be a proper value for vertical-align, or a proper fix for this use case?

Update: middle will obviously align the inline-block element with the middle of the line box. So far from my testing, it seems that as long as the element's bottom edge is above the baseline, there are no flickering issues animating height. To demonstrate the flicker issue which happens with text-align bottom/text-bottom (pay attention to the top border and text): demo

So a vertical-align of middle or text-top (to be safe) seem to work fine (avoiding top due to Chrome bug). I'm still open for insights.


Context: I'm using jQuery to animate an inline-block element. jQuery's animations (fadeIn/fadeOut/slideUp/slideDown/animate/etc) set overflow:hidden in the element while animating, causing the uncomfortable side-effect of having the whole page below an animated inline-block element to be slightly pushed down for the duration of the animation.

Here's another demo illustrating the paragraph above.


Code used in the SSCCEs:

Demo #1:

<div>
    some text and an inline block element <span></span>
</div>
<br>
<button>
    toggle overflow hidden
</button>

$('button').click(function() {
    var st = $('div')[0].style;
    st.overflow = !st.overflow ? 'hidden' : '';
});

span {
    display: inline-block;
    width: 10px;
    height: 50px;
    background: red;
}
div {
    display: inline-block;
}

Demo #2:

<div>
    some text and an inline block element <span></span>
</div>
<br>
<button>
    Animate for 1 second
</button>

$('button').click(function() {
    $('div').animate({ width: 300 }, 1000);
});

(same CSS as Demo #1)

Demo #3 flicker while animating height due to vertical-align: bottom:

baseline
<div>
    some text and an inline block element <span></span>
</div>
<br>
<button>
    Animate for 2 seconds
</button>

var i = 0;
$('button').click(function() {
    $('div').animate({ height: ++i % 2 ? 300 : 100 }, 2000);
});

span {
    display: inline-block;
    width: 10px;
    height: 50px;
    background: red;
}
div {
    display: inline-block;
    border: solid;
    vertical-align: bottom;
}
Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166

1 Answers1

1

You could cancel the "extra" height around the expanded baseline with a negative margin, but this will be dependent on the line-height of the parent. This is by default about 1.2 but if you set a specific value it becomes a lot easier to handle.

Here is an example that adds a negative margin while animating:

JS

$('div').
    addClass("animating").
    animate({ height: ++i % 2 ? 300 : 100 }, 2000).
    queue(function() {
        $(this).removeClass("animating").dequeue();
    });

CSS

.animating {
    margin-bottom: -.2em;
}

Assuming default font-size 16px, the line height is ~19.2px, so we need to remove 3.2px (in em, 3.2*100/16 = 0.2). Setting an actual line height value will make this easier, of course.

http://jsfiddle.net/n6hmr/9/

Nelson Menezes
  • 2,036
  • 14
  • 15
  • I believe the default line-height varies depending on the font and the browser, but thanks this is useful info. – Fabrício Matté Mar 05 '14 at 17:03
  • @FabrícioMatté Yes it does — if you want to use this technique I suggest you set the `line-height` using explicit values rather than the browser/font defaults. – Nelson Menezes Mar 06 '14 at 15:00