Vertical align glyphicon in bootstrap 3

matthijs picture matthijs · Mar 28, 2014 · Viewed 39.2k times · Source

I have a glyphicon as such:

<div class="col-xs-4 col-sm-2">
    <span class="glyphicon glyphicon-circle-arrow-up glyphicon-large"></span>
</div>
.glyphicon-large {
    min-height: 260px;
    font-size: 35px;
    width: 1em;
    display: block;
    top: 50%;
    margin: -0.5em auto 0px;
}

The glyphicon won't align to the center, vertically. When I open firefox, inspect element, and toggle off/on the top 50% rule, it suddenly works. How come?

Answer

KyleMit picture KyleMit · Jul 22, 2014

Browser Bug Explanation

According to MDN on top:

For relatively positioned elements (those with position: relative), it specifies the amount the element is moved below its normal position.
Note: Percentage is applied as a percentage of the height of the element's containing block

According to W3 on top:

For relatively positioned boxes, the offset is with respect to the top edges of the box itself (i.e., the box is given a position in the normal flow, then offset from that position according to these properties). Note: Percentages refer to height of containing block

Here's my guess:

I think what's happening is that when the browser is first rendering the visual tree, and sees top:50%;, it looks to the parent to set the height. Since no height has been specifically applied, and it has not loaded any child contents, the height of this div (and all divs) effectively starts off as zero until otherwise indicated. It then pushes down the glyph by 50% of zero.

When you toggle the property later, the browser has already rendered everything, so the calculated height of the parent container is provided by the height of its children.

Minimal, Complete, and Verifiable Example

Note: This doesn't really have anything to do with Bootstrap or Glyphicons. In order to avoid a dependency on bootstrap, we'll add top: 1px that would have been applied by the .glyphicon class. Even though it is overwritten by 50%, it still plays an important role.

Here's a simple set of parent/child elements:

<div id="container">
    <div id="child">Child</div>
</div>

In order to simulate the toggling the property in a more repeatable fashion, we can just wait two seconds and then apply a style in javascript like this:

window.setTimeout(function() {
    document.getElementById("child").style.top = '50%';
},2000);

Example 1 (jsFiddle)

As a starting point, let's recreate your issue.

#container {
    position: relative;
    
    /* For Visual Effects */
    border: 1px solid grey;
}
#child {
    position: relative;
    height: 50px;
    top: 1px;
    
    /* For Visual Effects */
    border: 1px solid orange;
    width: 50px;
    margin: 0px auto;
    
}

Notice that as soon as you resize the window, the browser will repaint the screen and move the element back to the top.

example1 screen

Example 2 (jsFiddle)

If you add top: 50% to the child element, nothing will happen when the javascript adds the property because it won't have anything to overwrite.

Example 3 (jsFiddle)

If you add top: 49% to the child element, then the DOM does have something to update so we'll get the weird glitch again.

Example 4 (jsFiddle)

If you add height: 50px; to the container instead of the child, then the top property has something to position against right from the get go and you don't need to use toggle in JavaScript.


How to Vertically Align

If you just wanted to know how to vertically center something consistently, then you can do the following:

The trick to vertically centering text is to set the line-height equal to the container height. If a line takes up 100 pixels, and the line of text online takes up 10, then browsers will try to center the text within the remaining 90 pixels, with 45 on the top and bottom.

.glyphicon-large {
    min-height:  260px;
    line-height: 260px;
}

Solution in jsFiddle