3

I recently noticed on a project that the ::after pseudoelement did not add any content after an input element:

input::after { content: "xxxxxxxxxx"; } // no "virtual last child" inserted into DOM "after" the input

(reference to "virtual last child" is from MDN page here)

Of course, an element such as a div will have content "after" it, and the last child "::after" will be inserted into the DOM:

div:empty::after { content: "xxxxxxxxxx"; }

//In DOM
<div>::after</div>

but nothing is inserted in these cases:

head, script { content: "qaqaqa"; }

My initial assumption was that any HTML elements that are rendered by the browser with tags that should be closed (.e.g, p, body, html, div,....etc) will have ::after inserted as a last child (and ::before inserted as a first-child), whereas elements that do NOT fit this (e.g., script, head, img, br, input,...etc) will not exhibit this behavior. My CodePen attempts suggested this was correct.

I read through documentation which finally led me to this resource, in which a note reads:

 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.

(for definition of "replaced elements" see here)

So now my refined assumption regarding ::after and ::before is that these pseudoelements are only applicable to "renderable" elements which cannot be classified as "replaced elements" (Note this refined assumption now excludes textarea from use with ::after / ::before, whereas my initial assumption would have included it - textarea::after was tested with CodePen and no ::after last child is inserted into the DOM).

Would the refined assumption be correct?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 1
    Related http://stackoverflow.com/questions/2587669/can-i-use-the-after-pseudo-element-on-an-input-field – DaniP Oct 11 '16 at 16:18

2 Answers2

5

HTML does not define which elements are replaced elements or which elements can contain ::before and ::after pseudo-elements. Neither do CSS2.1 or selectors-3. The latest rewrite of css-content-3, however, states pretty unambiguously:

Replaced elements do not have '::before' and '::after' pseudo-elements

although implementations of course are not consistent with the draft (famously or otherwise, WebKit/Blink) since this wasn't hitherto defined.

Whether an element can have ::before and ::after pseudo-elements is not defined by its content model (i.e. if it's void or otherwise), or whether it has an end tag, in HTML. And again, a lot of this is implementation-dependent. For example, some implementations allow br of all things to have ::before and ::after pseudo-elements, because nobody knows exactly how br is supposed to be implemented in terms of CSS and each browser does it its own way (because neither HTML nor CSS actually defines this).

A head element and any of its descendants can have ::before and ::after pseudo-elements — all you have to do is change their display to something other than none. Obviously, they're not supposed to be displayed, but that doesn't stop anyone trying to be clever.

As far as CSS is concerned, input and textarea are both considered replaced elements, even though textarea has a start tag, end tag, and content. Whether these elements should or must be replaced elements is not stated (not even in section 14.5 of WHATWG HTML), but most browsers render them as replaced elements by default, and this behavior usually can't be changed. And for the purposes of the ::before and ::after pseudo-elements not being supported, that's all that matters.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
0

Don't guess, read: https://drafts.csswg.org/selectors-3/#gen-content

The ::before and ::after pseudo-elements can be used to describe generated content before or after an element's content.

input has no content, so no after element is shown. Same applies for every HTML element with no content (br, menuitem, link...). All auto-closing tags have no content, and some others (like script) have none too.

Xenos
  • 3,351
  • 2
  • 27
  • 50
  • A valid textarea such as this ---> has content, but does not work with ::after/::before – The One and Only ChemistryBlob Oct 11 '16 at 16:06
  • 1
    I can't find the appropriate part of the spec, but pseudo-elements are rendered as HTML elements, therefore they can only be present in elements that can contain descendant HTML elements. – David Thomas Oct 11 '16 at 16:10
  • @DavidThomas, when I set a script tag to have display:inline and set a rule ---> script::after {content:"xxxxxx";}, the pseudo-element is in the DOM. Shouldn't – The One and Only ChemistryBlob Oct 11 '16 at 16:22
  • @TheOneandOnlyChemistryBlob `script` is fallen back to a text node (as in old browsers which do not recognized it), so I *guess* (that's where I should check specs and such) its content is considered as a normal text node and hidden by default (so shown if you set `display:inline`, and so it accepts `::after` and `::before` elements). – Xenos Oct 12 '16 at 07:39