Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I target a :before or :after pseudo-element with a sibling combinator?

Is there a reason why this CSS doesn't work?

http://jsfiddle.net/6v5BZ/

a[href^="http"]:after {     content:"";     width:10px;     height:10px;     display:inline-block;     background-color:red; }  a[href^="http"] img ~ :after {     display:none; } 

.. on this HTML?

<a href="http://google.com">Test</a> <a href="http://google.com">     <img src="https://www.google.com/logos/classicplus.png"> </a> 

The idea is to have a pseudo-element on matching anchor tags. But I do not want it to apply to anchor tags that wrap an image. And since I can't target anchors using something like a < img, I figured the maybe I could target the :after pseudo-element by finding an image that it's a sibling of.

Any insight would be greatly appreciated.

like image 980
jkupczak Avatar asked Oct 12 '11 04:10

jkupczak


People also ask

Can I have multiple before pseudo-elements for the same element?

In CSS2. 1, an element can only have at most one of any kind of pseudo-element at any time. (This means an element can have both a :before and an :after pseudo-element — it just cannot have more than one of each kind.)

What do the pseudo selectors before and after allow you to do?

CSS ::before and ::after pseudo-elements allow you to insert “content” before and after any non-replaced element (e.g. they work on a <div> but not an <input> ). This effectively allows you to show something on a web page that might not be present in the HTML content.

What can you do with the before pseudo-element?

The ::before pseudo-element can be used to insert some content before the content of an element.

Can pseudo-elements and pseudo-classes be combined?

There are no special rules around combining pseudo-classes and pseudo-elements, besides the one rule that says there can only be one pseudo-element per complex selector and it must appear at the very end.


2 Answers

You can't target :after since it's content is not rendered in the DOM and it does not manipulate it - for this to work the DOM would have to be re-rendered and CSS can't manipulate it like this.

Check the specification for detailed understanding: http://www.w3.org/TR/CSS2/generate.html#propdef-content

Generated content does not alter the document tree. In particular, it is not fed back to the document language processor (e.g., for reparsing).

I suggest you use JavaScript to do the job for you.

like image 107
easwee Avatar answered Sep 23 '22 01:09

easwee


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 a element.

It can be rewritten into the following:

a[href^="http"] img ~ *:after 

Notice the * 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:after (since 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 img
that is a descendant of an a (whose href starts with "http").

Since the 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.

In the case of a :before or :after pseudo-element, one might think of matching the pseudo-element's generating element relative to the pseudo-element's "sibling", but as the OP has correctly pointed out, there is no parent selector, so they're out of luck there, too.

like image 32
BoltClock Avatar answered Sep 23 '22 01:09

BoltClock