Vertical align middle on an inline-block anchor tag
Asked Answered
F

5

15

I have a need for my links and buttons to look the same, but I've been unable to vertically align the text within an "a" tag in the same manner as the "button" tag. It is important to note that the tags need to be able to handle multiple lines of text (so line-height will not work).

a,button {
  display: inline-block;
  -moz-box-sizing: border-box;
  width: 150px;
  height: 150px;
  vertical-align: middle;
  border: 1px solid #000;
  text-align: center;
}

See the jsfiddle below:

http://jsfiddle.net/bZsaw/3/

As you can see, I can get it to work with a combination of a span tag inside and setting "display:table" to the "a" and setting "display:table-cell" and "vertical-align:middle" to the span, but that doesn't work in IE7.

a,button {
    width: 150px;
    height: 150px;
    border: 1px solid #000;
    text-align: center;
}

a {
    display: table;
    -moz-box-sizing: border-box;
}

a span, button span {
    vertical-align: middle;
    text-align: center;
}

a span {
    display: table-cell; 
}

Looking for a simple CSS only solution.

Forepleasure answered 3/5, 2012 at 18:55 Comment(2)
I'm very sorry that you have to worry about IE7 :)Injurious
Still at 20% across all IE usage on our site. I catch myself looking at that number on a weekly basis. :)Forepleasure
M
15

The only reliable way to I've found align text vertically and allow wrapping of the text if it gets too long is with a 2 container approach.

The outer container should have a line height of at least double that specified for the inner container. In your case, that means the following:

a {
    width: 150px;
    height: 150px;
    border: 1px solid #000;
    text-align: center;
    line-height: 150px;
    display: block;
}

a span {
    display:inline;
    display:inline-table;
    display:inline-block;
    vertical-align:middle;
    line-height: 20px;
    *margin-top: expression(this.offsetHeight < this.parentNode.offsetHeight ? parseInt((this.parentNode.offsetHeight - this.offsetHeight) / 2) + "px" : "0");
}

Add float left on the a tag if you want everything inline. Here's the updated example with long text in the A tag too.. http://jsfiddle.net/bZsaw/13/

You can set the line height on the span to whatever you like and if it is less than half of the line height of the parent, it will center AND allow text wrapping if your text exceeds the parent container width. This works on all modern browsers as far as I know.

Maniple answered 3/5, 2012 at 19:4 Comment(3)
Close to marking this as the answer. Can you explain the chain of "display" settings?Forepleasure
The inline block is used to trigger hasLayout in IE7 which needs to happen it will have no effect on mozilla. It is quite fiddly really, but we have recently gone through this for input labels that need to vert align to the center and wrap where the label gets too long. Works very nicely.Maniple
Oops! I forgot the expression for IE7. I took it out of mine as I decided it was better to avoid expressions and let ie7 align top, but that may not be the case for you.Maniple
U
18

All answers are not updated,and all of them are basically hacks, you should use new CSS3 features, in this case flexbox

a,button {
  -moz-box-sizing: border-box;
  width: 150px;
  height: 150px;
  display:flex;/*CSS3*/
  align-items:center;/*Vertical align*/
  justify-content:center;/*horizontal align*/
  border: 1px solid #000;
}
<a href="#"><span>Testing 1,2,3</span></a>
    <button><span>Testing 1,2,3</span></button>

That should work for your problem, note that align-items and justify-content will behave the opposite if set flex-direction:vertical, default is flex-direction:row.

Feel free to use, all browsers support it caniuse.com/#search=flex

Also check out the free and excellent course flexbox.io/ he is the best teacher at this

Also check out css-grid, also new in CSS3

Uncritical answered 2/6, 2018 at 22:57 Comment(0)
M
15

The only reliable way to I've found align text vertically and allow wrapping of the text if it gets too long is with a 2 container approach.

The outer container should have a line height of at least double that specified for the inner container. In your case, that means the following:

a {
    width: 150px;
    height: 150px;
    border: 1px solid #000;
    text-align: center;
    line-height: 150px;
    display: block;
}

a span {
    display:inline;
    display:inline-table;
    display:inline-block;
    vertical-align:middle;
    line-height: 20px;
    *margin-top: expression(this.offsetHeight < this.parentNode.offsetHeight ? parseInt((this.parentNode.offsetHeight - this.offsetHeight) / 2) + "px" : "0");
}

Add float left on the a tag if you want everything inline. Here's the updated example with long text in the A tag too.. http://jsfiddle.net/bZsaw/13/

You can set the line height on the span to whatever you like and if it is less than half of the line height of the parent, it will center AND allow text wrapping if your text exceeds the parent container width. This works on all modern browsers as far as I know.

Maniple answered 3/5, 2012 at 19:4 Comment(3)
Close to marking this as the answer. Can you explain the chain of "display" settings?Forepleasure
The inline block is used to trigger hasLayout in IE7 which needs to happen it will have no effect on mozilla. It is quite fiddly really, but we have recently gone through this for input labels that need to vert align to the center and wrap where the label gets too long. Works very nicely.Maniple
Oops! I forgot the expression for IE7. I took it out of mine as I decided it was better to avoid expressions and let ie7 align top, but that may not be the case for you.Maniple
C
5

If your text won't be larger than the width of the box you could set the line-height equal to the height of the box.

line-height:150px;

Canonist answered 3/5, 2012 at 18:58 Comment(1)
Sorry, I should have mentioned that the button and a tags need to be able to handle multiple lines of text. I will edit the question.Forepleasure
E
0

The cleanest and most consistent way I found is this

display: grid;
place-items: center;

https://jsfiddle.net/j8bktum9/

Edrisedrock answered 1/10, 2020 at 4:25 Comment(0)
S
-3

Use line-height:150px; and display-inline:block;

Shetler answered 6/10, 2016 at 18:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.