140

I am trying to centre the link with the image, but can't seem to move the content vertically in any way.

<h4>More Information</h4>
<a href="#" class="pdf">File Name</a>

The icon is 22 x 22px

.pdf {
    font-size: 12px;
}
.pdf:before {
    padding:0 5px 0 0;
    content: url(../img/icon/pdf_small.png);
}
.pdf:after {
    content: " ( .pdf )";
    font-size: 10px;
}
.pdf:hover:after {
    color: #000;
}
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
theorise
  • 7,245
  • 14
  • 46
  • 65
  • 2
    Consider using flex: http://stackoverflow.com/a/22218694/435605 - the answer is for text but works on all elements. – AlikElzin-kilaka Nov 26 '15 at 17:20
  • Thanks to CSS3's [substring matching attribute selectors](https://www.w3.org/TR/css3-selectors/#attribute-substrings), you can now do `a[href$=".pdf"] { … }` and not even need the class. – Adam Katz Sep 29 '17 at 21:51
  • This seems to be the best answer for vertically centering content of :before/:after pseudo-elements: https://stackoverflow.com/a/14524161/470749 – Ryan Dec 04 '19 at 16:17

10 Answers10

163

Answered my own question after reading your advice on the vertical-align CSS attribute. Thanks for the tip!

.pdf:before {
    padding: 0 5px 0 0;
    content: url(../img/icon/pdf_small.png);
    vertical-align: -50%;
}
Christoph Bach
  • 598
  • 4
  • 9
theorise
  • 7,245
  • 14
  • 46
  • 65
32

You can also use tables to accomplish this, like:

.pdf {
  display: table;
}
.pdf:before {
  display: table-cell;
  vertical-align: middle;
}

Here is an example: https://jsfiddle.net/ar9fadd0/2/

EDIT: You can also use flex to accomplish this:

.pdf {
  display: flex;
}
.pdf:before {
  display: flex;
  align-items: center;
}

Here is an example: https://jsfiddle.net/ctqk0xq1/1/

fassl
  • 724
  • 7
  • 9
  • 2
    neither of these fiddles work on Chrome 52 – stealthwang Aug 22 '16 at 21:37
  • both of them work for me on Chrome Version 52.0.2743.116 (64-bit) (Linux) – fassl Aug 24 '16 at 11:34
  • 2
    neither works on OSX. http://imgur.com/bqUQ09X – stealthwang Aug 24 '16 at 19:40
  • the question was about vertically aligning :before and :after elements and thats what the fiddles do, also in your screenshot – fassl Aug 26 '16 at 07:04
  • "I am trying to centre the link with the image" that isn't done in either example or my screenshot – stealthwang Sep 19 '16 at 16:33
  • Works as a charm nowadays. Used for a tiny icon that indicates a master-detail row in a table and aligns perfectly in the middle dynamically (resizing the window makes the element larger and smaller and the icon stays vertically centered (chrome)) – Youp Bernoulli Sep 15 '17 at 14:32
31

I'm no CSS expert, but what happens if you put vertical-align: middle; into your .pdf:before directive?

Chowlett
  • 45,935
  • 20
  • 116
  • 150
14

I think a cleaner approach is to inherit the vertical alignment:

In html:

<div class="shortcut"><a href="#">Download</a></div>

And in css:

.shortcut {
    vertical-align: middle;
}
.shortcut > a:after {
    vertical-align: inherit;
{

This way the icon will align properly in any resolution/font-size combination. Great for use with icon fonts.

Sander van den Akker
  • 1,545
  • 11
  • 13
11

Using flexboxes did the trick for me:

.pdf:before {
    display: flex;
    align-items: center;
    justify-content: center;
}
David Refoua
  • 3,476
  • 3
  • 31
  • 55
8

This is what worked for me:

.pdf::before {
    content: url('path/to/image.png');
    display: flex;
    align-items: center;
    justify-content: center;
    height: inherit;
}
Gjaa
  • 1,461
  • 1
  • 19
  • 20
6

Messing around with the line-height attribute should do the trick. I haven't tested this, so the exact value may not be right, but start with 1.5em, and tweak it in 0.1 increments until it lines up.

.pdf{ line-height:1.5em; }
Mathew
  • 8,203
  • 6
  • 37
  • 59
5

I spent a good amount of time trying to work this out today, and couldn't get things working using line-height or vertical-align. The easiest solution I was able to find was to set the <a/> to be relatively positioned so it would contain absolutes, and the :after to be positioned absolutely taking it out of the flow.

a{
    position:relative;
    padding-right:18px;
}
a:after{
    position:absolute;
    content:url(image.png);
}

The after image seemed to automatically center in that case, at least under Firefox/Chrome. Such may be a bit sloppier for browsers not supporting :after, due to the excess spacing on the <a/>.

4

I just found a pretty neat solution, I think. The trick is to set the line-height of image (or any content) height.

text

Using CSS:

div{
  line-height: 26px; /* height of the image in #submit span:after */
}

span:after{
    content: url('images/forward.png');
    vertical-align: bottom;
}

That would probably also work without the span.

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
JoomFever
  • 41
  • 1
3

I had a similar problem. Here is what I did. Since the element I was trying to center vertically had height = 60px, I managed to center it vertically using:

top: calc(50% - 30px);