You cannot use a combinator to target a pseudo-element relative to elements other than its generating element.
This is because they're pseudo-elements, not actual elements, and combinators only work by establishing relationships between actual elements. A pseudo-element, on the other hand, can only be applied to the subject of a selector (the rightmost compound selector), and this happens only after matching is processed on the real elements. In other words, matching is done first as though the pseudo-element wasn't there, then the pseudo-element, if it's indicated within the selector, is applied to each match.
In your code, the following selector:
a[href^="http"] img ~ :after
Does not actually look for an
:after pseudo-element that comes after an
img within the
a, even though it appears that way as both are rendered as children of the
It can be rewritten into the following:
a[href^="http"] img ~ *:after
* selector, which is implied. Similarly to how you can omit
* before any other simple selectors for it to be implied, omitting
* from a pseudo-element also makes it implied to be there. See the spec for details.
Now, even though it appears
*:after should still match
a would match
*), it still doesn't work that way. If you remove the
:after pseudo-element from the selector:
a[href^="http"] img ~ *
You'll notice that the meaning of the selector changes entirely:
Select any element
that appears as a following sibling of an
that is a descendant of an
href starts with "http").
img is the last child of the
a element in your HTML, there are no following siblings to match, and therefore no
:after pseudo-elements can be generated.