Browser Bug Explanation
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
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:
<!-- language: lang-html -->
<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:
<!-- language: lang-js -->
window.setTimeout(function() {
document.getElementById("child").style.top = '50%';
},2000);
As a starting point, let's recreate your issue.
<!-- language: lang-css -->
#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.
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.
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.
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.
<!-- language: lang-css -->
<pre><code>.glyphicon-large {
min-height: 260px;
<b>line-height: 260px;</b>
}
</code></pre>