3

It seems CSS is right associative, and unlike programming languages, you cannot influence this with parentheses.

I have this general structure:

<div>
   <div class='pizza'></div>
</div>
<p>Select me!  Select me!</p>

<div>
   <div class="pizza">
      <p>Do NOT select me!</p>
   </div>
</div>

I can't figure out the selector for a <p> that follows a sibling <div> containing a <div class="pizza">.

I tried this but the right-to-left associativity of CSS does not yield what I want:

div > div.pizza + p

I know this isn't right.

Can someone offer a pointer?

Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
Tom Baxter
  • 1,980
  • 2
  • 17
  • 35
  • Not possible with current CSS3 selectors. – CBroe Apr 20 '15 at 19:56
  • 4
    You can't since `.pizza` is not a sibling of the `p` element. There is [no parent selector in CSS3](http://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector). – Josh Crozier Apr 20 '15 at 19:56
  • If you need to style those `

    ` elements, I would recommend adding a class to them, or to the parent element, so that you can use `.parent > p`

    – TylerH Apr 20 '15 at 20:21
  • This isn't about CSS being right associative. In fact, it *isn't* - it's actually left associative, and this matters in some situations. But not this one, because `div > div.pizza` doesn't mean "a `div` with a child of `div.pizza`", it means "a `div.pizza` whose parent is a `div`". The right-associative interpretation of this chain of combinators, `div > (div.pizza + p)`, and the left-associative interpretation `(div > div.pizza) + p`, have the same ultimate meaning, so the direction of associativity doesn't matter in this case. – Mark Amery May 22 '17 at 22:34

2 Answers2

4

Combinators, at least the ones that are currently available, can only express a relationship between exactly two elements. As you've correctly observed, you cannot change the associativity of combinators. Because of this, and the fact that there is no parent counterpart to the > combinator for child elements, it is not possible to construct a CSS selector that represents both

div > div.pizza

and

div + p

where the first div in each selector represents the same element.

This associativity issue can be solved using the proposed :has() pseudo-class, which provides you with a relative selector syntax within a functional pseudo-class, allowing you to construct such selectors as

div:has(> div.pizza) + p

where p is the subject of the outermost selector. The relative selector > div.pizza is scoped to the first div selector — essentially, this is a combination of both of the first two complex selectors above, with the :has() pseudo-class acting just like any other simple selector.

It is not known yet if this proposed feature will be implemented in CSS.

See my answers to these related questions for more info:

Community
  • 1
  • 1
BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
0

You can't (yet) select your chosen <p> using standard CSS selectors.

You can, however, deploy the axe CSS selector extension library which will enable you to write selectors in your stylesheet which select parents, ancestors, previous siblings and remote elements.

Here is an example:

p {
color: rgb(191, 191, 191);
}


.pizza < div + p {
font-weight: bold;
font-size: 24px;
color: rgb(255, 0, 0);
}
<div>
   <div class="pizza"></div>
</div>
<p>Select me!  Select me!</p>

<div>
   <div class="pizza">
      <p>Do NOT select me!</p>
   </div>
</div>

<script src="https://rouninmedia.github.io/axe/axe.js"></script>

Further Reading on axe Selectors:

http://www.rounin.co.uk/projects/axe/axe2.html

Rounin
  • 21,349
  • 4
  • 53
  • 69