Css Selector For "Foo That Contains Bar"

CSS selector for foo that contains bar?

No, what you are looking for would be called a parent selector. CSS has none; they have been proposed multiple times but I know of no existing or forthcoming standard including them. You are correct that you would need to use something like jQuery or use additional class annotations to achieve the effect you want.

Here are some similar questions with similar results:

  • Is there a CSS parent selector?
  • CSS Parent/Ancestor Selector
  • Complex CSS selector for parent of active child

Why do 'foo bar' and 'foo bar' have the same specificity in CSS?

This has actually been brought up in the working group mailing list, way back when, in this thread.

It basically comes down to, yes, intuitively a selector with a combinator looks more specific, but an algorithm, extended form the current one, with this in mind becomes much more complicated than the "simple" triplets used now, which is pretty confusing for people as it is.

Finally,


While this could have been the case, this is one of the few things in CSS2
that have been interoperably implemented for years, and therefore won't
change in CSS2.1.

"If it ain't broke, don't fix it." seemed to be the final call.

The CSS selector for an element that its id is in the foo:bar form

According to the W3c spec linked to in this answer, using colons in element IDs is plain wrong if used unescaped.

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-z0-9] and ISO 10646 characters U+00A1 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item). For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".

Is the JSF framework really outputting those IDs in the final rendered HTML?

Two classes in :not() selector

The :not pseudo class takes a simple selector, so use i.e. the attribute selector

p:not([class="foo bar"]) {  color: #ff0000;}
<p class="foo">This is a (.foo) paragraph.</p><p class="bar">This is a (.bar) paragraph.</p><p class="foo bar">This is a (.foo.bar) paragraph.</p><p>This is a normal paragraph.</p>

How do I do an and selector?

Concatenate the selector. So you would use .foo.bar {}

How to apply CSS to elements that have multiple classes?

Solutions




  1.  .foo.bar { ... }

  2.  [class="foo bar"] { ... }             // explicit class name

  3.  [class~="foo"][class~="bar"] { ... }  // inclusive class name

:has vs :matches - Selectors Level 4

In a nutshell:

  • E:has(rs1, rs2) matches E when a different element F matches any of the selector arguments in relation to E. If you know jQuery's :has() selector, this is exactly the same thing.

  • E:matches(s1, s2) matches E when E itself matches any of the selector arguments. Think of :matches() as the direct opposite of :not(), which matches E if E itself does not match any of the arguments.1 You can also think of :matches() as a pseudo-class version of jQuery's .filter() method.

    This notation is equivalent to concatenating every selector argument with E (provided you can actually concatenate them) such that you have a selector list (E)(s1), (E)(s2). For example, div:matches(.foo, .bar) is equivalent to div.foo, div.bar.

This fundamental difference is demonstrated most straightforwardly with the selectors div:matches(p) and div:has(p):

  • div:has(p) matches any div element that has a p descendant.
    This is very similar to div p, except the former targets the div
    and the latter targets the p.

  • Since a div can never be a p, div:matches(p) will never match
    anything. (Likewise, div:not(p) will match all div elements.)


Here's a more complex example with slightly less absurd selectors:

div:has(.foo, .bar)
div:matches(.foo, .bar)

With the following markup:

<div class="foo"></div> <!-- [1] -->
<div class="bar"></div> <!-- [1] -->

<div class="foo bar"> <!-- [2] -->
<p></p>
</div>

<div> <!-- [3] -->
<p class="foo"></p>
</div>

<div> <!-- [3] -->
<div> <!-- [3] -->
<p class="bar"></p>
</div>
</div>

<div> <!-- [4] -->
<div class="foo"> <!-- [5] -->
<p class="bar"></p>
</div>
</div>

Which elements are matched by which selectors?

  1. Matched by div:matches(.foo, .bar)

    The first div element has the "foo" class, and the second div element has the "bar" class, so each of these satisfies its respective selector argument in the :matches() pseudo-class.

  2. Matched by div:matches(.foo, .bar)

    The third div element has both classes, so it matches both selector arguments.

    A note on specificity: both of these arguments have equal specificity, making the total specificity (0, 1, 1), but when an element matches multiple selector arguments with different specificity values, the spec says that the specificity is that of the most specific argument that is matched.

  3. Matched by div:has(.foo, .bar)

    Each of these div elements has a descendant element (in this case, a p) with a class that matches its respective selector argument in the :has() pseudo-class.

  4. Matched by div:has(.foo, .bar)

    This div element has a div.foo descendant and a p.bar descendant, therefore it satisfies both relative selector arguments.

    A note on specificity: because :has() is not yet in the fast profile and is therefore tentatively excluded from CSS, the concept of specificity does not apply at all. There are plans to include a limited version of this in the fast profile for use in CSS, but there is nothing concrete as yet. Any new developments will be added at an appropriate time.

  5. Matched by div:matches(.foo, .bar) and div:has(.foo, .bar)

    This div element matches both pseudo-classes:

    • it is .foo (as it has the "foo" class), and
    • it has a descendant with the "bar" class.

    This element would also match div:matches(.foo, .bar):has(.foo, .bar), which would be a valid level 4 selector since a compound selector can have any combination of pseudo-classes.

Another difference between :matches() and :has() is that :has() accepts what's known as a relative selector. A relative selector has a scope; selector scoping is an entire topic in its own right, but for the purposes of :has(), the scoping element is always the element you attach the :has() pseudo-class to. But, more importantly, a relative selector can either have an implicit descendant combinator, or begin explicitly with a combinator such as >, + or ~ — this combinator is what links the rest of the relative selector to its scoping element.

For example, while :has() defaults to an ancestor-descendant relationship, you can pass a relative selector that begins with + and it then becomes an adjacent-sibling relationship: ul:has(+ p) matches any ul element that is directly followed by a p (and not necessarily one that contains a p descendant).

As for :matches(), while the overview table says that it accepts a list of compound selectors, AFAIK it hasn't yet been set in stone whether it will take a list of compound selectors or complex selectors, and in which profile (fast or complete). But a compound selector is simply the new name for what Selectors 3 currently calls a sequence of simple selectors and a complex selector is an entire series of compound selectors and combinators. A relative selector is more like a complex selector in that respect. See this answer for a non-exhaustive list of the various terms used in selectors.


1 Yes, that's "arguments" in plural — in Selectors 4, :not() can now accept a list of selectors as opposed to a single simple selector. A much-needed enhancement, but it's also to make it consistent with the other new functional pseudo-classes.



Related Topics



Leave a reply



Submit