Search code examples
csscross-browserwebkitmozillavendor-prefix

Why do browser prefixes for text-align have different behaviour and which is correct?


I want to vertically centre <div> tags that have a horizontal margin between each other.

The problem is that this behavior appears to be inconsistent between text-align: center and text-align: -webkit-center or text-align: -moz-center:

.parent {
  display: inline-block;
  border: 1px dotted #fd0;
  position: relative;
}
.parent.ta {
  text-align: center;
}
.parent.browser-ta {
  text-align: -webkit-center;
  text-align: -moz-center;
}
.child {
  display: inline-block;
  vertical-align: top;
}
.child > .content {
  display: block;
  margin: 0 10px;
  border: 1px solid #888;
  width: 200px;
  text-align: left;
}
.wrong {
  background-color: #e00;
  color: #fff;
}
.right {
  background-color: #0a3;
  color: #fff;
}
<div>
  Using <tt>text-align: center</tt>;
  <div class="parent ta">
    <div class="child">
      <div class="content wrong">child 1 LEFT</div>
      <div class="parent ta">
        <div class="child">
          <div class="content">child a</div>
        </div>
        <div class="child">
          <div class="content">child b</div>
        </div>
        <div class="child">
          <div class="content">child c</div>
        </div>
      </div>
    </div>
    <div class="child">
      <div class="content wrong">child 2 LEFT</div>
      <div class="parent ta">
        <div class="child">
          <div class="content">child d</div>
        </div>
        <div class="child">
          <div class="content">child e</div>
        </div>
        <div class="child">
          <div class="content">child f</div>
        </div>
      </div>
    </div>
    <div class="child ">
      <div class="content right">child 3 CENTRE</div>
    </div>
  </div>
</div>
<br>
<br>
<div>
  Using <tt>text-align: -vendor-center</tt>
  <div class="parent browser-ta">
    <div class="child">
      <div class="content right">child 1 CENTRE</div>
      <div class="parent browser-ta">
        <div class="child">
          <div class="content">child a</div>
        </div>
        <div class="child">
          <div class="content">child b</div>
        </div>
        <div class="child">
          <div class="content">child c</div>
        </div>
      </div>
    </div>
    <div class="child">
      <div class="content right">child 2 CENTRE</div>
      <div class="parent browser-ta">
        <div class="child">
          <div class="content">child d</div>
        </div>
        <div class="child">
          <div class="content">child e</div>
        </div>
        <div class="child">
          <div class="content">child f</div>
        </div>
      </div>
    </div>
    <div class="child">
      <div class="content right">child 3 CENTRE</div>
    </div>
  </div>

Run that snippet and the two similar HTML and CSS produce different layouts in Chrome (Webkit/Blink) and FireFox. The red panels are in the wrong location, the green ones are correct.

So text-align: -webkit-center and text-align: -moz-center appear to be correct (to me) but text-align: center appears to be bugged in both browsers.

Digging out the venerable old <centre> tag (that we're not supposed to use) and that works right too (though examining it reveals it uses the browser prefix too).

Is this correct? Is this a bug? Is there a reason for the difference? Which one should I use?


Solution

  • The prefixed values are described by MDN to be "block alignment values", which means block boxes themselves are aligned in addition to the inline content within them. This is the exact behavior of the <center> element, and the prefixed values are in fact intended for that element — if you look in the UA stylesheets for each engine you'll find a ruleset that says exactly center { display: block; text-align: -vendor-center; }.

    The reason text-align: center is not implemented this way is because text-align is designed to affect inline-level boxes (as evidenced by the "text-" in its name), not block-level boxes. But that, I suspect, is not the answer you're really looking for.

    What's happening is that the boxes that are actually being aligned in your snippet are the .content elements, which are block boxes, not inline-blocks. The reason that last element is being centred is because its parent, an inline-block, is being shrink-wrapped, and itself then centred by the text-align: center declaration in its ancestor.