'Proper way to position :before pseudo-elements

What is the proper way to position :before and :after pseudo-elements, like pictures? I've been messing around with a bunch of different ways, but none of them seem like very elegant solutions.

This is what I'm trying to do:

enter image description here

This is what I did:

div.read-more a:before {
    content: url('/images/read_more_arrow_sm.png');
    position: absolute;
    top: 4px;
    left: -15px;
}

<div class="read-more">
    <a href="#">Read More</a>
</div>

I basically just want the image to be aligned with the text. Is there another way to do that?

It would be perfect if I could just use padding and margins on the :before image, and that is supposed to be what you do. But for some reason, that hasn't been working for me. I can add horizontal padding and margins, but top and bottom padding doesn't do anything. Why would that happen?



Solution 1:[1]

Try using background instead of content and put a placeholder in content:

div.read-more a:before {
  background: url('https://i.stack.imgur.com/XyerX.jpg') CENTER CENTER NO-REPEAT;
  content: url('https://i.stack.imgur.com/Icd9n.png');
  /* 21x21 transparent pixels */
  width: 21px;
  height: 21px;
}
<div class="read-more">
  <a href="#">Read More</a>
</div>

https://jsfiddle.net/7X7x2/1/

Solution 2:[2]

You can use the following code in order to move the content:

div.read-more a:before {
  content: "\00BB \0020";
  position: relative;
  top: -2px;
}

Solution 3:[3]

If you want only to position image near the text, then you probably need vertical -align property:

div.read-more a:before {
    vertical-align: bottom;
    content: url(image.png);
}

It have following possible values: baseline, sub, super, top, text-top, middle, bottom, text-bottom

This values a calculated from the position of the text from the current text line (Read more in the example).

Full reference: http://www.w3schools.com/cssref/pr_pos_vertical-align.asp

(To add space before text just use margin-right)

Solution 4:[4]

This was my solution, with a mouseover:

div.read-more a:before {
    content: url(image.png);
    position: relative;
    top: 3px;
    left: -7px;
    padding-left: 7px;
}
div.read-more a:hover:before {
    content: url(image_hover.png);
}

Solution 5:[5]

Right now the easiest way to position these is using the flex container.

Bring in the image using background image, give it the required width and height, and make sure the the image is contained. Doing this controls the size, regardless of how big the image in your url is(compared to the uncontrolled approach in content:url())

div.read-more a:before {
    content:'';
    background-image: url('/images/read_more_arrow_sm.png');
    width:25px; //or any size you prefer
    height:25px;
    background-size:cover;
}

And on the container element, which in your case is the anchor tag,

<div class="read-more">
    <a href="#">Read More</a>
</div>

declare a flex container

div.readmore a{
    display: inline-flex; //or simply 'flex', whatever works for you
    align-items:center;
}

This approach using flexbox is much more intuitive than using arbitrary pixel values using position:absolute and top/left keywords.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Oleg Valter is with Ukraine
Solution 2 Mo.
Solution 3 Alexey Ivanov
Solution 4 Bas
Solution 5 sayandcode