Reputation: 413
I'm trying to create some buttons for a website using styled hyperlinks. I have managed to get the button looking how I want, bar one slight issue. I can't get the text ('Link' in the source code below) to vertically center.
Unfortunately there may be more than one line of text as demonstrated with the second button so I can't use line-height
to vertically center it.
My initial solution was to use display: table-cell;
rather than inline-block
, and that sorts the issue in Chrome, Firefox and Safari but not in Internet Explorer so I'm thinking I need to stick to inline-block.
How would I go about vertically centering the link text within the 57px
x 100px
inline-block
, and have it cater to multiple lines of text? Thanks in advance.
.button {
background-image:url(/images/categorybutton-off.gif);
color:#000;
display:inline-block;
height:57px;
width:100px;
font-family:Verdana, Geneva, sans-serif;
font-size:10px;
font-weight:bold;
text-align:center;
text-decoration:none;
vertical-align:middle;
}
.button:hover {
background-image:url(/images/categorybutton-on.gif);
}
.button:before {
content:"Click Here For\A";
font-style:italic;
font-weight:normal !important;
white-space:pre;
}
<a href="/" class="button">Link</a>
<a href="/" class="button">Link<br />More Details</a>
Upvotes: 41
Views: 49808
Reputation: 40315
You do not need to create any wrapper elements or anything for this... just use inline flex (or grid, but I'll describe flex) and center stuff, like this (it's just the same as doing it with non-inline flex, but with an added vertical-align
to set a sane baseline for the element):
.button {
display: inline-flex;
flex-direction: column;
justify-content: center;
text-align: center;
vertical-align: middle;
}
<a href="/" class="button">Link</a>
<a href="/" class="button">Link<br />More Details</a>
This will also work for dynamic height content.
Going through each of those; so first there's the obvious one:
display: inline-flex;
Next, since ::before
is being used, there are two child items (the ::before
and the text). Since I guess we want them vertically stacked, we'll need to set the direction (because default is "row"):
flex-direction: column; /* PS: this defines the "main" axis */
Then, since we want the elements packed and centered along the vertical aka column aka main axis (if you use the "row" flex direction, you'd use align-content
here instead):
justify-content: center;
And since we want to center the text, with each line individually centered (remember that each item defaults to filling the cross aka horizontal axis, so they're already full width):
text-align: center;
Technically this is enough, except since this is an inline element the baselines will be all over the place (based on content), so we can set them to something consistent and reasonable:
vertical-align: middle; /* align *this* element in the *parent*! */
And that's it; just applied directly to the element. No inner divs or wrappers or anything needed.
If you've only got one child element (e.g. no ::before
or whatever) then it doesn't really matter what the flex direction is, so you can shorten the CSS a bit by using the defaults:
/* if there's just one child, or you want to */
/* arrange children horizontally: */
.button {
display: flex;
align-content: center;
text-align: center;
vertical-align: middle;
}
You can also drop vertical-align
if the element's container is positioning it acceptably and you don't need to tweak the baseline.
By the way, the same can be done with an inline grid layout if you prefer -- a single-row/column grid has a lot of functional overlap with flex:
/* using grid instead: */
.button {
display: inline-grid;
grid: max-content / auto;
align-content: center;
text-align: center;
vertical-align: middle;
}
/* this is the important bit: */
/* ------------------------------------------------------*/
.button {
display: inline-flex;
flex-direction: column;
justify-content: center;
text-align: center;
vertical-align: middle;
}
/* ------------------------------------------------------*/
/* other styling from OP; not relevant to the centering. */
/* important props removed & displayed above instead. */
.button {
background-image:url(/images/categorybutton-off.gif);
color:#000;
/*display:inline-block;*/
height:57px;
width:100px;
font-family:Verdana, Geneva, sans-serif;
font-size:10px;
font-weight:bold;
/*text-align:center;*/
text-decoration:none;
/*vertical-align:middle;*/
}
.button:hover {
background-image:url(/images/categorybutton-on.gif);
}
.button:before {
content:"Click Here For\A";
font-style:italic;
font-weight:normal !important;
white-space:pre;
}
/* placeholders for missing images: */
.button { background-color: #AAA; }
.button:hover { background-color: #DDD; }
this <a href="/" class="button">Link</a> is
<a href="/" class="button">Link<br />More Details</a> text
<br/><br/>
<a href="/" class="button" style="width:unset;height:unset;padding:1em;">......... fixed sizes ........</a>
<a href="/" class="button" style="width:unset;height:unset;padding:1em;">are<br/><br/><br/>not<br/><br/><br/>required</a>
Upvotes: 7
Reputation: 1313
Riffing off the other answers, in case anyone's designing a button and seeking this page one can combine:
button
design with display:inline-flex
button-content
div nested within with display:inline-block
button-text
span to define things like text-decoration overrides (necessary for buttons not to have underlined text in pages where parent elements define it - notably on chrome & safari)Upvotes: 0
Reputation: 14094
Wrap your text with a span (Centered), and write another empty span just before it(Centerer) like this.
HTML:
<a href="..." class="button">
<span class="Centerer"></span>
<span class='Centered'>Link</span>
</a>
CSS
.Centered
{
vertical-align: middle;
display: inline-block;
}
.Centerer
{
display: inline-block;
height: 100%;
vertical-align: middle;
}
Take a look here: http://jsfiddle.net/xVnQ6/
Upvotes: 26
Reputation: 1030
Many thanks @avrahamcool, works like a charm!
I have a little upgrade. You can replace redundant .Centerer span with css
.button:before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
See demo here: http://jsfiddle.net/modernweb/bXD2V/
NOTE: This will not work with text in "content" attribute.
Upvotes: 38