What's the difference between `.class1.class2` and `.class1 .class2` CSS rule? - css

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

Related

CSS rule is executed with and without :not() selector [duplicate]

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.

CSS selector for elements of specified class that are not contained in element with another class [duplicate]

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.

Is the CSS :not() selector supposed to work with distant descendants?

Here is the official documentation for the CSS3 :not() pseudo-class:
http://www.w3.org/TR/css3-selectors/#negation
and the proposed CSS Selectors Level 4 enhancement:
http://dev.w3.org/csswg/selectors4/#negation
I've been searching the implementation and browser support for :not(), but the only examples I found were with a single element or with a direct child of an element, e.g.:
div *:not(p) { color: red; }
The example above works when <p> is a direct child of <div>, but it does not work when <p> is a more distant descendant of <div>.
div :not(p) {
color: red;
}
<div>
<ul>
<li>This is red</li>
</ul>
<p>This is NOT</p>
<blockquote><p>This is red but is not supposed to be!</p></blockquote>
</div>
If the answer is in the official documentation above, then I didn't find/understand it. As I said, I have searched this site and the web but couldn't find any discussion about the support or lack thereof of :not() as grand-children of another element.
Is this supposed to work like I think it should?
Is this supposed to work like I think it should?
No, the behavior you're seeing is correct.
In your last example, although the <blockquote> contains a <p>, it's the <blockquote> itself that's matching *:not(p), as well as the condition that it must be a descendant of the <div>, which it is. The style is applied only to the <blockquote>, but it is then inherited by the <p> inside it.
The <p> element itself still counts against the negation, so the <p> itself is still being excluded from your selector. It's just inheriting the text color from its parent, the <blockquote> element.
Even if none of its relatively close ancestors matched the selector, you have elements like html and body to worry about as well — although you could probably just tack on a body selector in the very beginning:
body div...
This is why I often strongly advise against using the :not() selector for filtering descendants, especially when not qualified with a type selector (like div in your example). It doesn't work the way most people expect it to, and the use of inherited properties like color only serves to compound the problem, on top of making it even more confusing for authors. See my answers to these other questions for more examples:
Why doesn't this CSS :not() declaration filter down?
CSS negation pseudo-class :not() for parent/ancestor elements
The solution to the problem described is to simply apply a different color to <p> elements. You won't be able to simply exclude them with a selector because of inheritance:
/* Apply to div and let all its descendants inherit */
div {
color: red;
}
/* Remove it from div p */
div p {
color: black;
}
On Selectors Level 4: yes, :not() has indeed been enhanced to accept full complex selectors that contain combinators. Essentially, this means (once browsers begin implementing it) you will be able to write the following selector and have it do exactly what you want:
p:not(div p) {
color: red;
}
In case anyone is interested, this works in jQuery today.
The color is assigned to the blockquote, and is then inherited by the p.
:not(p) just makes it so that the styles are not directly applied. They are still inherited though.

What is the correct terminology for this kind of CSS declaration ".myClass div"?

What is the correct terminology when referring to a CSS declaration containing CSS combinators, such as:
.myClass div { ... }
Here I'm using a declaration which will apply styles to all div elements inside an element with the class myClass.
But that is irrelevant. I'm interested in knowing the correct terminology for a declaration which mentions parent selectors.
But what is the correct terminology for this sort of declaration?
They're called descendant selectors:
http://www.w3.org/TR/CSS2/selector.html#descendant-selectors
A descendant selector is made up of two or more selectors separated by
white space. A descendant selector of the form "A B" matches when an
element B is an arbitrary descendant of some ancestor element A.
They are called Descendant Selectors, see here for more information and other terms
Just in case the W3 site ever goes down ;) here are the important parts:
At times, authors may want selectors to match an element that is the
descendant of another element in the document tree (e.g., "Match those
EM elements that are contained by an H1 element").
Descendant selectors express such a relationship in a pattern. A descendant
selector is made up of two or more selectors separated by white space.
A descendant selector of the form "A B" matches when an element B is
an arbitrary descendant of some ancestor element A.
Example (also quoted from the site linked above):
For example, consider the following rules:
h1 { color: red }
em { color: red }
Although the intention of these rules is to add emphasis to text by changing its color, the effect will be lost in a case such as:
<H1>This headline is <EM>very</EM> important</H1>
We address this case by supplementing the previous rules with a rule that sets the text color to blue whenever an EM occurs anywhere within an H1:
h1 { color: red }
em { color: red }
h1 em { color: blue }

CSS select first element with a certain class

What is the syntax for selecting the first element with a certain class? Please specify whether that method of selection is part of CSS3 or CSS2.1.
If you need the first element with a certain class among its siblings, you can use
.myclass {
/* styles of the first one */
}
.myclass ~ .myclass {
/* styles of the others (must cancel the styles of the first rule) */
}
Don't try to use .myclass:not(.myclass ~ .myclass) to do this in only one rule, it won't work since :not() only accepts simple selectors in the parentheses.
If you want the first .myclass in the whole document, there is no way to do it with CSS alone.
The :nth-of-type() or :nth-child() approaches posted are wrong, even if they coincidentally happen to match the elements you want in your page.
Browser support of sibling selector (~): IE7+ and all others.
This problem sucks as bad as the solutions. IMO you should just give the first element a class of .first{} programmatically.
Try this
.testparent .test:first-child {
color: red;
}
<div class="testparent">
<div class="test">test</div>
<div class="test">test</div>
<div class="test">test</div>
</div>
the first div 'test' has red color only.
.class-name:first-of-type {
⋮ declarations
}

Resources