9

Usually people try to figure out how to vertically center stuff, I want to remove an instance of centered content and align and I'm stuck.

The content of the button (that is placed in a list in a table cell) is vertically centered by default. How can I remove this? How to align the contents of the <button> vertically to the top?

<table>
 <tbody>
 <td>
  <ul>
  <li>
   <button>
    <div>Content</div>

I have an example on jsFiddle.

button {
  display: block;
  position: relative;
  background-color: pink;
  width: 100%;
  min-height: 200px;
}
<button>
  <div>why?</div>
  <div>are these centered vertically?</div>
  <div>And how to remove it?</div>
</button>
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
primavera133
  • 1,284
  • 1
  • 15
  • 24
  • possible duplicate of [Top-align text within button element?](http://stackoverflow.com/questions/16244860/top-align-text-within-button-element) – Ole Haugset Oct 02 '14 at 12:04
  • [jsfiddle](http://jsfiddle.net/0jjozb7L/18/) try this JS Fiddle – jrenk Oct 02 '14 at 12:08
  • sorry @jrenk, I cannot use position:absolute, I really want to use position:static – primavera133 Oct 02 '14 at 12:28
  • @primavera133 I don't why but the content inside the button are vertically middle by default even if you don't use the bootstrap and table, for example - http://jsfiddle.net/44pz6f74/ and to fix the issue you could apply the `min-height: 200px;` to your `li` instead of the `button` like this demo - http://jsfiddle.net/9wwm7hp2/ – Anonymous Oct 02 '14 at 12:41

2 Answers2

10

Why the contents are vertically centered?

There's no specific reason. This is the way UAs handle the position of value/content of buttons (including <button>, <input type="button">)1.

How to remove vertical centering?

Well, there's a way to achieve that. First, a little background is needed.

But before that, you should note that <div> elements are supposed to be used where flow contents are expected. This means that they are NOT allowed to be placed inside <button> elements.

As per HTML5 spec (Which is at PR state right now):

Content model for element button:
Phrasing content, but there must be no interactive content descendant.

Therefore, a valid HTML could be like this:

<button>
    why? <br>
    are these centered vertically? <br>
    And how to remove it?
</button>

Background

In an inline flow, inline-level elements (inline, inline-block) can be aligned vertically inside the parent by vertical-align property. Using that with a value other than baseline makes inline-level elements position somewhere other than the baseline of the parent (which is the default place).

The key point is that taller elements would affect the line box / baseline.

The Solution

First, in order to handle the position of the lines, we need to wrap them by a wrapper element like <span> as follows:

<button>
    <span> <!-- Added wrapper -->
        why? <br>
        are these centered vertically? <br>
        And how to remove it?
    </span>
</button>

In cases that the parent - the <button> in this case - has an explicit height, by any chance if we could have a child element having the exact same height of the parent, we would be able to expand the height of the line box and surprisingly make our desired in-flow child - the nested <span> in this case - be aligned to the top vertically by vertical-align: top; declaration.

10.8 Line height calculations: 'vertical-align' property

This property affects the vertical positioning inside a line box of the boxes generated by an inline-level element.

top
Align the top of the aligned subtree with the top of the line box.

EXAMPLE HERE

button { width: 100%; height: 200px; }

button > span {
    display: inline-block;
    vertical-align: top;
}

button:after {
    content: "";
    display: inline-block;
    vertical-align: top;
    height: 100%;
}

Last bot not least, if you'd like to use min-height rather than height for the button, you should use min-height: inherit; for the pseudo-element as well.

EXAMPLE HERE.


1 Chrome and Firefox also display the value of text inputs vertically at the middle while IE8 doesn't for instance.

Community
  • 1
  • 1
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
  • +0001) Isn't the button element used for a single line of text and the text will always be vertically aligned in the middle no matter what height you apply and div isn't allowed as child of button element, Right? – Anonymous Oct 02 '14 at 17:29
  • 1
    @MaryMelody ` – Hashem Qolami Oct 02 '14 at 17:58
0

Bootstrap adds padding above and below the button content (6 pixels). You can alter the padding amount with: button{padding:0px;} or button{padding-top:x; padding-bottom:y;} where x and y are whatever value you choose.

If you want to alter that button only give the button id="table" or something like that and then do: button#table{padding:0px;}

If you can avoid using vertical align you should as not all browsers support it.

spasticninja
  • 681
  • 8
  • 16