Search code examples
jquery-animatewidthoverflowhtml

Making a <span> element inline-block and overflow: hidden will displace him?


Please use any browser and have a look at this fiddle that is trying to represent the structure I am currently using on a new website I'm building (hover your mouse over the "hello" text!):

http://jsfiddle.net/3A6fC/

$(function () {
    $('#hello').on('mouseenter', function (e) {
        // Animate "world" width, creating a fold out effect:
        $('#world').css('width', 40);
    });
});
div.container {
    background-color: lightblue;
}

ul {
    list-style-type: none;
}

#world {
    transition: width 2s;
    display: inline-block;
    width: 0;
    overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
<div class="container">
    <ul>
        <li>
            <span id="hello">hello</span>
            <span id="world">world</span>
            <span>..</span>
        </li>
    </ul>
</div>

As you can see, I am trying to animate the expansion of some text, occuring on the inside of a <li>. I figure that I should be able to make the secret text have no width (be invisible), and then quite straight forwardly animate the width to full width (in this simple example, I use a fixed width as one can not animate to "auto").

Problem is that inline elements do not care about a provided width, so I have to make him be displayed as inline-block. Doing so will give the element 0 pixels width. However, the text is still shown. So I must also apply the CSS rule overflow: hidden. But hiding the overflow introduces yet another problem, the one I can not explain: The span element is displaced. The text "world" is offset to the top and looks like some dumb superscript.

I can ugly hack the span element a bit more, into this fiddle:

http://jsfiddle.net/3A6fC/1/

But as you can see, now we have a problem with the dots at the end of the sentence not moving along..

If you know why this problem has occured (it gotta have something to do with the span being inline-block?) and how to fix the problem would be super awesome!


Solution

  • The direct answer to why it happens is from this paragraph in the CSS 2.1 spec which appears at the very bottom of Section 10:

    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.

    The underlying reason as to why the spec says that is unclear, but it may have something to do with the difficulties in implementing overflow settings other than visible.

    The simplest fix in your scenario is just to take all three spans off the baseline. The text is all the same height, so vertical-align:top, vertical-align:middle and vertical-align bottom will all do the trick.

    e.g. li span { vertical-align:top; }

    see http://jsfiddle.net/3A6fC/5/