CSS :after not adding content to certain elements
Solution 1:
img
and input
are both replaced elements.
A replaced element is any element whose appearance and dimensions are defined by an external resource. Examples include images (
<img>
tags), plugins (<object>
tags), and form elements (<button>
,<textarea>
,<input>
, and<select>
tags). All other elements types can be referred to as non-replaced elements.
:before
and :after
only work with non-replaced elements.
From the spec:
Note. This specification does not fully define the interaction of
:before
and:after
with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.
With span:before, span:after
, the DOM looks like this:
<span><before></before>Content of span<after></after></span>
Evidently, that won't work with <img src="" />
.
Solution 2:
:before
and :after
are not required to work for replaced elements, and CSS specifications do not specify how they would work for them, and the concept of replaced element is somewhat vague.
The CSS 2.1 specification clearly suggests that they can work for replaced elements, just saying that it does not “fully define” how. This relates to the issue that a replaced element is expected to have its own visual rendering, which is not controlled by CSS, whereas the pseudo-elements should add something to the content of the element. The spec adds that this will be defined “in more detail” in a future specification, but this has not taken place so far.
Browser vendors just decided to avoid problems by not implementing these pseudo-elements for some elements at all.
It is not clear at all what “replaced element” means, and the meaning appears to have changed somewhat. It is often interpreted as meaning the same as empty element (an element with EMPTY
declared content, i.e. an element that cannot have any content), but CSS 2.1 itself shows a sample style sheet with the selector br:before
(though browsers have ignored this, implementing br
their own way). It can be argued that more and more elements have moved into the scope of CSS rendering, at least in part. For example, an input
element (incuding its font, colors, etc.) is largely controllable with CSS in modern browsers.
Current browsers (Firefox, IE, Chrome) do not seem to support the :after
and :before
pseudo-elements for empty elements other than hr
. For hr
, IE and Chrome place the generated content inside a bordered box, which is the implementation of hr
; the content makes the box taller. Firefox places the content of both (!) pseudo-elements after the horizontal rule that is its implementation of hr
. This variation illustrates the kinds of “interaction” problems that are referred to in CSS 2.1.
It is often claimed that these pseudo-elements cannot be used for empty elements since their HTML definitions do not allow any content. This is a category error. The syntax rules of a markup language do not restrict what you can do in CSS
To conclude, :after
and :before
are currently not usable for empty elements (except marginally for hr
), but this is mainly due to implementations and may change in the future.