In the below example, I want to create a CSS rule that applies only to the header with the text "Blockhead".
<div class="gumby">
<span class="pokey"></span>
<h3>Blockhead</h3>
<h3>Clay rules</h3>
</div>
Can I use parentheses, such as (.gumby > .pokey) + h3? If not, what is my alternative?
No, parentheses are not valid operators in CSS selectors. They are reserved for functional notations, such as :lang(), :not(), and :nth-child().
You don't need them anyway; .gumby > .pokey + h3 by itself will work just fine.
This is because a sequence of selectors and combinators is always read linearly. Combinators don't have any sort of precedence. The selector can be interpreted as
Select an h3 element
that immediately follows an element with class pokey
that is a child of an element with class gumby.
And because of how node trees work, the use of sibling and child combinators here implies that both .pokey and the h3 are children of .gumby, which in your case they are, because of its statement that both of them are siblings.
As of 2022, we can now use the :is() selector for this purpose:
https://developer.mozilla.org/en-US/docs/Web/CSS/:is
:is(.gumby > .pokey) + h3 {
color: blue;
}
<div class="gumby">
<span class="pokey"></span>
<h3>Blockhead</h3>
<h3>Clay rules</h3>
</div>
If I understand correctly, :is() can simulate both logical AND :is(A):is(B):is(C) and logical OR :is(A, B, C), allowing for powerful combinations. Don't forget to use it in concert with other structural pseudo-classes such as :not() and :nth-child(), CSS Combinators, and DOM Traversal methods such as document.querySelectorAll().
Also, the :where() pseudo-class is identical except that it has 0 specificity, while :is() takes the specificity of its most specific argument.
h3 is not inside .pokey so you must ommit .pokey from the rule
All u'd be able to do is
.gumby h3 {}
or do this
<div class="gumby pokey">
<h3>Blockhead</h3>
<h3>Clay rules</h3>
</div>
.gumby.pokey h3 {}
if a tag has more than one class you can pile them up in css if you don't use a space character
Related
This is driving me nuts:
HTML:
<div><h1>Hello World!</h1></div>
CSS:
*:not(div) h1 { color: #900; }
Doesn't this read, "Select all h1 elements that have an ancestor that is not a div element...?" Thus, "Hello World!" should not be coloured red, yet it still is.
For the above markup, adding the child combinator works:
*:not(div) > h1 { color: #900; }
But doesn't affect the h1 element if it is not a child of a div element. For example:
<div><article><h1>Hello World!</h1></article></div>
Which is why I'd like to indicate the h1 element as a descendant, not a child, of the div element. Anyone?
Doesn't this read, "Select all h1 elements that have an ancestor that is not a div element...?"
It does. But in a typical HTML document, every h1 has at least two ancestors that are not div elements — and those ancestors are none other than body and html.
This is the problem with trying to filter ancestors using :not(): it just doesn't work reliably, especially when the :not() is not being qualified by some other selector such as a type selector or a class selector, e.g. .foo:not(div). You'll have a much easier time simply applying styles to all h1 elements and overriding them with div h1.
In Selectors 4, :not() has been enhanced to accept full complex selectors containing combinators, including the descendant combinator. Whether this will be implemented in the fast profile (and thus CSS) remains to be tested and confirmed, but once it is implemented, then you will be able to use it to exclude elements with certain ancestors. Due to how selectors work, the negation has to be done on the element itself and not the ancestor in order to work reliably, and therefore the syntax will look a little different:
h1:not(div h1) { color: #900; }
Anyone who's familiar with jQuery will quickly point out that this selector works in jQuery today. This is one of a number of disparities between Selector 3's :not() and jQuery's :not(), which Selectors 4 seeks to rectify.
The <html> element is not a <div>. The <body> element is not a <div>.
So the condition "has an ancestor that is not a <div>" will be true for all elements.
Unless you can use the > (child) selector, I don't think you can do what you're trying to do - it doesn't really make sense. In your second example, <article> is not a div, so that matches *:not(div) too.
Just wondering what the difference is between CSS (selectors 4) pseudo selectors :has and :matches
The spec http://dev.w3.org/csswg/selectors-4/#overview says:
E:matches(s1, s2)
an E element that matches compound selector s1 and/or compound selector s2
§4.2 The Matches-any Pseudo-class: :matches()
E:has(rs1, rs2)
an E element, if either of the relative selectors rs1 or rs2, when evaluated with E as the :scope elements, match an element
§4.4 The Relational Pseudo-class: :has()
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?
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.
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.
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.
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.
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.
I saw the following snippet in a css file. What does it do?
h3 ~ *:not(h3) {
margin-left: 15px;
}
Obviously it alters h3 headers in some way but I don't understand what ~ *:not(h3) does.
Googling ~ *:not(h3) is unproductive.
The isn't HTML. It is a CSS selector.
Specifically, it is the negation pseudo-class:
The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument.
Obviously it alters h3 headers
No, it does exactly the opposite. It stops the selector from matching h3 elements.
This is CSS, not HTML. See Mozilla's documentation on the CSS negation pseudo class for more details, but not basically selects elements that do not match the specified selector (in this case, h3).
I am trying the :not pseudoclass selector, I want everything on the page to have color blue except the childs of a div which class="pag", so I wrote:
:not(.pag > p){
color:blue;
}
<div class="pag">
<p>First</p>
<p>Second</p>
<p>Thirt</p>
<article>Blah blah blah</article>
</div>
but it doesnt seem to work. Can somebody explain me why?
http://jsfiddle.net/Rc9pT/
It works fine if you simplify the selector:
.pag > :not(p){
color:blue;
}
JS Fiddle demo.
Albeit this 'works fine' only with the caveat that you have to specify a selector, with this approach, for every parent-child relationship; which may become burdensome.
I suspect that it's the simplicity that's required:
The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument.
A 'simple selector' is defined as:
either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
This seems to imply that any selector incorporating combinators (such as white-space, >, + or ~, among others) is not 'simple', unfortunately.
References:
Negation (:not()) pseudo-class.
Simple selector definition.
I have a table with some rows:
<table>
<tr class="even"><td>tr0</td></tr>
<tr><td>tr1</td></tr>
<tr class="even"><td>tr2</td></tr>
</table>
I have a CSS rule (rule1) for even rows:
.even{
background-color: blue;
}
I have another rule (rule2) for override the bgcolor of any row:
.override, .override.even{
background-color: green;
}
The weird thing is in IE9 all even rows (with no override class) are green!
Developer tools shows this for even rows:
In these two conditions IE do the job correctly:
If I rewrite rule2 like this:
.override, .override .even{ ... }
If I move rule2 above rule1:
.override, .override.even{ ... }
.even { ... }
Question is what's the difference between .override.even and .override .even?
EDIT:
Thanks for replies. Another question which I forgot to ask is why IE shows the even rows green?
Spacing in between class specifiers means a ascendant -> descendant relationship.
The rule:
.test .heading { font-weight: bold; }
Would apply to the <p> element here:
<span class="test"><p class="heading">Something</p></span>
The lack of space means that the element must have both classes for the rule to apply.
The rule:
.heading.major { color: blue; }
Would apply to the <p> element here:
<p class="heading major">Major heading</p>
Both answers are right, but they don't explain, why IE shows both rows green.
It's because IE has "standard" and "quirks" mode. To make multiple classes selectors work, you need to use proper DOCTYPE at the beginning of the file.
You are in "quirks" mode now and IE don't support multiple selectors, it sees only latest class. So it sees this and rows are green:
.even {
background-color: blue;
}
.override, .even {
background-color: green;
}
Put
<!DOCTYPE html>
(or another DOCTYPE) at the beginning of the file and both rows are going to be blue as expected.
See the W3C [CSS] Selector (Level 3) "Recommendation":
.override .even is two simple selectors separated by a space (which is the descendant combinator, CSS is whitespace-sensitive):
At times, authors may want selectors to describe an element that is the descendant of another element in the document tree (e.g., "an EM element that is contained within an H1 element"). Descendant combinators express such a relationship. A descendant combinator is whitespace that separates two sequences of simple selectors. A selector of the form "A B" represents an element B that is an arbitrary descendant of some ancestor element A.
This selector will match elements that have the class even if and only if there exists an ancestor -- not necessarily the parent! -- element with the class override. (Unlike characters in some movies, an element is never it's own ancestor ;-)
.override.even is a simple selector sequence:
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.
A simple selector sequence is evaluated as the conjunction of the individual simple selectors applied to the same element: that is, it will only match elements with both the override and even classes applied.
Happy coding.
.override .even is interpreted as "some element with an 'override' class, with another element with a .even class nested within. It's basically the same as ul li, but applying to CSS classes.
override.even is interpreted as "some single element with BOTH override AND even classes".
<div class="class1">
<div class="class2">
<p>test1</p>
</div>
</div>
If this type coded added than use space between to class like .class1 .class2
<div class="class1 class2">
<p>test2</p>
</div>
If this type coded added than don't use space between to class like .class1.class2