CSS Selector for Adjacency

2019-01-20 06:59发布

问题:

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?

回答1:

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:

  • Are parentheses allowed in CSS selectors?
  • How do I select an element based on the state of another element in the page with CSS?


回答2:

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