Difference between : and :: in CSS [duplicate] - css

This question already has answers here:
What is the difference between :before and ::before?
(5 answers)
Closed 9 years ago.
What exactly is the difference between : and :: in CSS?
For example, I see CSS code like:
.example:before{
content:'just one';
}
and
.example2::before{
content:'here two';
}
What is the difference? What is best practice?

Pseudo-classes
The pseudo-class concept is introduced to permit selection based on information that lies outside of the document tree or that cannot be expressed using the other simple selectors.
A pseudo-class always consists of a "colon" (:) followed by the name of the pseudo-class and optionally by a value between parentheses.
ref: http://www.w3.org/TR/css3-selectors/#pseudo-classes
Pseudo-elements
Pseudo-elements create abstractions about the document tree beyond those specified by the document language. For instance, document languages do not offer mechanisms to access the first letter or first line of an element's content. Pseudo-elements allow authors to refer to this otherwise inaccessible information. Pseudo-elements may also provide authors a way to refer to content that does not exist in the source document (e.g., the ::before and ::after pseudo-elements give access to generated content).
A pseudo-element is made of two colons (::) followed by the name of the pseudo-element.
ref: http://www.w3.org/TR/css3-selectors/#pseudo-elements
We typically used to use just a single colon for everything, but now the best practice is to follow the W3C's guidelines, though I would add a caveat that you want to ensure the browsers you are supporting understands the syntax before you start making wholesale changes to your stylesheets.

Related

What is the difference between E:dir(dir) and E[dir="dir"] in CSS? [duplicate]

This question already has answers here:
What's the difference between html[lang="en"] and html:lang(en) in CSS?
(4 answers)
Closed 6 years ago.
W3C is introducing a new pseudo-class for direction detection in Selectors 4. I am wondering what is the difference between that and a normal attribute selector:
CSS2 - attribute selector
E[dir="rtl"] { ... }
Selectors 4 - dir pseudo-class
E:dir(rtl) { ... }
Is there a specific reason for creating a new pseudo-class for that? Are these selectors identical or do they behave differently? Are there any performance or specificity implications?
Is there a specific reason for creating a new pseudo-class for that?
The same reason the :lang() pseudo-class was introduced alongside attribute selectors in CSS2.1 See What's the difference between html[lang="en"] and html:lang(en) in CSS?
Are these selectors identical or do they behave differently?
See my answer to the linked question. Here's the relevant quotation from Selectors 4 for the sake of completeness:
The difference between :dir(C) and ''[dir=C]'' is that ''[dir=C]'' only performs a comparison against a given attribute on the element, while the :dir(C) pseudo-class uses the UAs knowledge of the document’s semantics to perform the comparison. For example, in HTML, the directionality of an element inherits so that a child without a dir attribute will have the same directionality as its closest ancestor with a valid dir attribute. As another example, in HTML, an element that matches ''[dir=auto]'' will match either :dir(ltr) or :dir(rtl) depending on the resolved directionality of the elements as determined by its contents. [HTML5]
To drive the point home on the similarities between :dir() and :lang(), if you look closely the first sentence is in fact a word-for-word copy of the same paragraph in the section describing :lang().
Much of the rest of the text for :lang() is new, however, because along with :dir(), Selectors 4 also introduces enhanced functionality for :lang().
Are there any performance or specificity implications?
Since the answer to your previous question is that they behave differently, performance is irrelevant.
No specificity implications because pseudo-classes and attribute selectors are equally specific.
1 It's not clear to me why it took almost 15 years for :dir() to be added to Selectors, but there you go.
According to MDN, some subtle differences exist:
The :dir CSS pseudo-class matches elements based on the directionality
of the text contained in it. In HTML, the direction is determined by
the dir attribute. For other document types there may be other
document methods for determining the language.
Note that the usage of the pseudo-class :dir() is not equivalent of
using the [dir=…] attribute selectors. The latter matches a value of
the dir and doesn't match when no attribute is set, even if in that
case the element inherits the value of its parent; similarly [dir=rtl]
or [dir=ltr] won't match the auto value that can be used on the dir
attribute. In the opposite, :dir() will match the value calculated by
the UA, being inherited or the auto value.
Also :dir() considers only the semantic value of the directionality,
the one defined in the document, most of the time in HTML. It won't
consider styling directionality, the one set by CSS properties like
direction which are purely stylistic.

CSS Rule Set Selector

I recently completed an assignment that had this question:
Within a CSS rule set, a selector includes
a selector and a declaration block
a selector and a value
a property and a selector
a property and a value
The correct answer given was option 4.
I don't quite agree with the answer. In fact, none of the answers seem correct to me, but I wanted to make sure I wasn't misunderstanding the question.
I would appreciate if someone could confirm if the question is flawed or explain the answer if it was indeed correct.
As W3C (World Wide Web Consortium says, a selectors are:
patterns that match against elements in a tree, and as such form one of several technologies that can be used to select nodes in an XML document.
Mozilla Developer Network describes CSS rules here.
Indeed, a CSS rule includes a selector, a property and a value.
Personally, the sintax of the question is a bit awkward, but it is not flawed.
In CSS A "rule set" (or just "rule") consist of a "selector" and a "declaration block".
A "declaration block" consists of "declarations" between curly brackets.
Each "declaration" contains a "property", a colon and a "value" separated from each other within the "declaration block" by a semi-colon.
So you are right. None of the options match, and option 4 is the definition of a "declaration", not a "selector".
See 4.1.7 Rule sets, declaration blocks, and selectors and 4.1.8 Declarations and properties
It's correct:
div { margin: 0; }
The whole line is a rule set
div is a selector
margin is a property
0 is a value

Should I use single colons (:) or double colons (::) for before, after, first-letter and first-line pseudo-elements?

From MDN:
The :: notation was introduced in CSS 3 in order to establish a
discrimination between pseudo-classes and pseudo-elements. Browsers
also accept the notation : introduced in CSS 2.
If the notation : will always be accepted by CSS3 browsers, should I use it because it works on old and new browsers?
Or should I use both of them, : for old browsers and :: for new ones, because the notation : won't be always accepted?
Note: I think my question isn't a duplicate isn't a duplicate of Should I use single or double colon notation for pseudo-elements? because the other question asks about single vs double notation for ALL pseudo-elements; while my question is only about pseudo-elements defined in CSS2, not the new ones defined in CSS3, because I already know that with those I must use ::.
For what it's worth, Selectors 4 now explicitly instructs1 authors to use double colons for all pseudo-elements, including CSS1 and CSS2 pseudo-elements, going forward (emphasis mine):
Because CSS Level 1 and CSS Level 2 conflated pseudo-elements and pseudo-classes by sharing a single-colon syntax for both, user agents must also accept the previous one-colon notation for the Level 1 & 2 pseudo-elements (::before, ::after, ::first-line, and ::first-letter). This compatibility notation is not allowed any other pseudo-elements. However, as this syntax is deprecated, authors should use the Level 3+ double-colon syntax for these pseudo-elements.
This means that the only appropriate use of the single-colon syntax today is if you absolutely require legacy browser support — the only browser that matters here is IE8 and older. If you don't, you should use the double-colon syntax for the sake of consistency with newer pseudo-elements which will only accept double colons. Besides, it's quite pointless to use the single-colon syntax if, for instance, you're going to apply properties that aren't supported by IE8 anyway, such as border-radius or box-shadow, to your ::before and ::after pseudo-elements.
I'd like to believe that Selectors 3 at the very least implied this in its statement that the single-colon syntax does not apply to any newer pseudo-elements, but having this sort of thing stated in black and white never hurt anybody and it's good to know that the upcoming standard does just that.
Also, there is absolutely no reason to write duplicate rules with both notations in the same stylesheet (e.g. :before, :after { ... } ::before, ::after { ... }), as no browser in existence supports the new syntax without supporting the older one.
1 I say this fully aware that it probably didn't state this yet at the time this question was asked — the May 2013 WD certainly did not.
As I mentioned in this comment previously - http://css-tricks.com/html5-progress-element/#comment-533395
Short Answer – Use single colon notation :
Long Answer – There’s no real difference between :before and ::before, or between :after and ::after. But since the older browsers use a single colon notation, so using : is always a safer bet. Read this spec defined by W3C on pseudo elements which states that,
This :: notation is introduced by the current document in order to establish a discrimination between pseudo-classes and pseudo-elements. For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after). This compatibility is not allowed for the new pseudo-elements introduced in CSS level 3.
I would would go for the single :
People now a days should at least have somewhat of the latest browsers installed, so you have nothing to worry about.

Invalid CSS selector causes rule to be dropped: What is the rationale?

I'm looking more for links to mailing list discussions, etc. rather than speculation.
Can anyone help me find out the rationale behind the quoted error handling rules from the CSS Selectors Level 3 spec.
User agents must observe the rules for handling parsing errors:
a simple selector containing an undeclared namespace prefix is invalid
a selector containing an invalid simple selector, an invalid combinator or an invalid token is invalid.
a group of selectors containing an invalid selector is invalid.
Specifications reusing Selectors must define how to handle parsing errors. (In the case of CSS, the entire rule in which the selector is used is dropped.)
I had the following rule:
#menu li.last, #menu li:last-child {
...
}
To compensate for IE8's lack of last-child support, I used a class and a JavaScript shim. However, this didn't work because IE8 complies with the CSS spec on error handling, and discards the entire rule because it doesn't recognise one selector. This can be fixed by separating the two selectors in to individual rules.
Why is this desirable? Why doesn't the spec suggest simply discarding the unrecognised selector, but keeping the rest of the rule?
I'd like to know the rationale, as the rules currently seem counter-intuitive.
Why is this desirable? Why doesn't the spec suggest simply discarding the unrecognised selector, but keeping the rest of the rule?
The short answer is because it'd be too difficult for implementations to figure out what exactly constitutes "the rest of the rule" (or "the rest of the selector list" for that matter) without getting it wrong and inadvertently messing up layouts, as well as for consistency in error handling, and forward compatibility with future specifications.
I'll preface my long answer with a link to another answer of mine, on handling of invalid selectors. A comment on that answer points directly to section 4.1.7 of the CSS2.1 spec on dealing with errors in selectors within rule sets, which mentions commas in selectors as an example. I think it sums it up pretty nicely:
CSS 2.1 gives a special meaning to the comma (,) in selectors. However, since it is not known if the comma may acquire other meanings in future updates of CSS, the whole statement should be ignored if there is an error anywhere in the selector, even though the rest of the selector may look reasonable in CSS 2.1.
While the comma itself still means grouping two or more selectors as far as selectors are concerned, it turns out that Selectors 4 introduces new functional pseudo-classes that accept selector groups (or selector lists) as arguments, such as :matches() (it even changes :not() so it accepts a list, making it similar to :matches(), whereas in level 3 it only accepts a single simple selector).
This means that not only will you find comma-separated groups of selectors associated with rules, but you'll start finding them within functional pseudo-classes as well (note that this is within a stylesheet only; outside of CSS, selectors can appear in JavaScript code, used by selector libraries and the native Selectors API).
Although not the only reason by far, this alone is enough to potentially over-complicate a parser's error handling rules with a huge risk of breaking the selector, the rule set, or even the layout. In the event of a parsing error with a comma, the parser will have trouble determining whether this selector group corresponds to an entire rule set, or part of another selector group, and how to handle the rest of the selector and its associated rule set accordingly. Instead of trying to guess, risk guessing wrongly and breaking the rule in some way (e.g. by matching and styling all the wrong elements), the safest bet is to discard the rule and move on.
As an example, consider the following rule, whose selector is valid in level 4 but not in level 3, taken from this question of mine:
#sectors > div:not(.alpha, .beta, .gamma) {
color: #808080;
background-color: #e9e9e9;
opacity: 0.5;
}
A naïve parser that doesn't understand Selectors 4 may try to split this into three distinct selectors that share the same declaration block, instead of a single selector with a pseudo-class that accepts a list, based on the commas alone:
#sectors > div:not(.alpha
.beta
.gamma)
If it simply discards the first and last selectors which are obviously invalid, leaving the second selector which is valid, should it then try to apply the rule to any elements with class beta? It's clearly not what the author intends to do, so if a browser does that, it's going to do something unexpected to this layout. By discarding the rule with the invalid selector, the layout looks just a little saner, but that's an over-simplified example; rules with layout-altering styles can cause even bigger problems if applied wrongly.
Of course, other ambiguities in selector parsing can occur too, which can lead to the following situations:
Not knowing where the complex selector ends
Not knowing where the selector list ends
Not knowing where the declaration block begins
A combination of the above
All of which, again, are most easily resolved by discarding the rule set instead of playing the guessing game.
In the case of seemingly well-formed selectors that are unrecognized, such as :last-child as a pseudo-class in your example, the spec makes no distinction between unrecognized selectors and selectors that are just plain malformed. Both result in a parsing error. From the same section that you link to:
Invalidity is caused by a parsing error, e.g. an unrecognized token or a token which is not allowed at the current parsing point.
And by making that statement about :last-child I'm assuming the browser is able to parse a single colon followed by an arbitrary ident as a pseudo-class in the first place; in reality you can't assume that an implementation will know to parse :last-child as a pseudo-class correctly, or something like :lang() or :not() with a functional notation since functional pseudo-classes didn't appear until CSS2.
Selectors defines a specific set of known pseudo-classes and pseudo-elements, the names of which are most likely hardcoded in every implementation. The most naïve of parsers have the entire notation for each pseudo-class and pseudo-element, including the single/double colon(s), hardcoded (I wouldn't be surprised if the major browsers actually do this with :before, :after, :first-letter and :first-line as a special case). So what may seem like a pseudo-class to one implementation might very well be gobbledygook to another.
Since there are so many ways for implementations to fail, the spec makes no distinction, making error handling much more predictable. If a selector is unrecognized, no matter whether it's because it's unsupported or malformed, the rule is discarded. Simple, straightforward, and easy enough to get your head around.
All that said, there is at least one discussion in the www-style public mailing list suggesting that the specification be changed because it may not be so difficult to implement error handling by splitting selectors after all.
I should also mention that some layout engines behave differently, such as WebKit ignoring non-WebKit-prefixed selectors in a rule, applying its own prefixes, while other browsers ignore the rule completely (you can find more examples on Stack Overflow; here's a slightly different one). In a way you could say WebKit is skirting the rule as it is, although it does try to parse comma-separated selector groups smartly in spite of those prefixed selectors.
I don't think the working group has a compelling reason to change this behavior yet. In fact, if anything, they have a compelling reason not to change it, and that's because sites have been relying on this behavior for many years. In the past, we had selector hacks for filtering older versions of IE; today, we have prefixed selectors for filtering other browsers. These hacks all rely on the same behavior of certain browsers discarding rules they don't recognize, with other browsers applying them if they think they're correct, e.g. by recognizing prefixes (or throwing only the unrecognized ones out, as WebKit does). Sites could break in newer versions of those browsers if this rule were to change, which absolutely cannot happen in such a diversified (read: fragmented) Web as ours.
As of April 2013, it was decided in a telecon that this behavior remain unchanged for the reason I've postulated above:
- RESOLVED: Do not adopt MQ-style invalidation for Selectors
due to Web-compat concerns.
Media query-style invalidation refers to invalid media queries in a comma-separated list not breaking the entire #media rule.

What's the difference between html[lang="en"] and html:lang(en) in CSS?

The CSS language pseudo-class to allow us specify different styles for different languages, like so:
html:lang(en) .foo { ... }
However, this doesn't work in IE7, so I've been using an attribute selector:
html[lang="en"] .foo { ... }
They seem to do the same thing, but are there any subtle differences? And if not, why does CSS even have a language pseudo-class, when the attribute selector does the exact same thing?
In HTML, both the :lang() pseudo-class and the attribute selector will match an element with the corresponding lang attribute.
The difference is that a browser may have other ways of determining the language of a given element when testing against the :lang() pseudo-class which may be defined by the document language and/or the implementation, whereas an attribute selector will only check an element for that given attribute, without any accompanying document-based semantics.
For example, in HTML, the pseudo-class will also match any of the element's descendants for which there isn't a different lang, depending on how a browser determines the language for those descendants. Usually, the descendants will inherit the language attribute from their ancestor if it is not explicitly set.
Here's what the spec says:
The difference between :lang(C) and the ‘|=’ operator is that the ‘|=’ operator only performs a comparison against a given attribute on the element, while the :lang(C) pseudo-class uses the UAs knowledge of the document's semantics to perform the comparison.
In this HTML example, only the BODY matches [lang|=fr] (because it has a LANG attribute) but both the BODY and the P match :lang(fr) (because both are in French). The P does not match the [lang|=fr] because it does not have a LANG attribute.
<body lang=fr>
<p>Je suis français.</p>
</body>
Notice the specific phrasings of "has a LANG attribute" and "are in French". These two phrases have very different meanings in English, as you might imagine.
In your example, the following selector will also match your .foo element:
.foo:lang(en)
But the following selectors won't, if it doesn't have its own lang attribute set:
.foo[lang="en"]
.foo[lang|="en"]
As for browser support, the :lang() pseudo-class is supported starting from IE8, so IE7 really is the only browser you will be unable to support by using the pseudo-class over the attribute selector.
Based on this understanding you can then answer the question "which should I use": you should always use the :lang() pseudo-class by default, unless certain quirks (or the need to support IE7) require working around by using an attribute selector instead.
Selectors 4 not only brings enhanced functionality to the :lang() pseudo-class (thereby widening the gap in functionality between it and attribute selectors), but also introduces the :dir() pseudo-class for matching elements based on their directionality. Because directionality is a language-related property, the dir and lang attributes work similarly in HTML, and the difference between :dir() and its corresponding attribute selector is analogous to that between :lang() and its corresponding attribute selector — to the point where the first sentence of the following quotation is in fact a word-for-word copy of the same paragraph in the section describing :lang():
The difference between :dir(C) and ''[dir=C]'' is that ''[dir=C]'' only performs a comparison against a given attribute on the element, while the :dir(C) pseudo-class uses the UAs knowledge of the document’s semantics to perform the comparison. For example, in HTML, the directionality of an element inherits so that a child without a dir attribute will have the same directionality as its closest ancestor with a valid dir attribute. As another example, in HTML, an element that matches ''[dir=auto]'' will match either :dir(ltr) or :dir(rtl) depending on the resolved directionality of the elements as determined by its contents. [HTML5]
One more thing that wasn't mentioned by anybody else - :lang() pseudoclass isn't interested in how one sets the element's language. In XHTML document (true XHTML with XML MIME type), you can use xml:lang="en" and the element will match :lang(en) but not [lang="en"].
According to the spec,
If the document language specifies how the human language of an element is determined, it is possible to write selectors in CSS that match an element based on its language. For example, in HTML [HTML4], the language is determined by a combination of the "lang" attribute, the META element, and possibly by information from the protocol (such as HTTP headers). XML uses an attribute called xml:lang, and there may be other document language-specific methods for determining the language.
The pseudo-class ':lang(C)' matches if the element is in language C. Whether there is a match is based solely on the identifier C being either equal to, or a hyphen-separated substring of, the element's language value, in the same way as if performed by the '|=' operator. The matching of C against the element's language value is performed case-insensitively for characters within the ASCII range. The identifier C does not have to be a valid language name.
That is:
It works for the many other ways of specifying a language besides the simple lang attribute.
Most importantly, as detailed in #BoltClock's answer, it will use the language specified (in whatever manner) on a container element, not just on the element itself, since language is inherited by child elements.
It uses |= semantics, i.e. :lang(en) and :lang(us) will both match span[lang=en-us].
It is guaranteed to be case-insensitive, whereas
The case-sensitivity of attribute names and values in selectors depends on the document language.
Css supports attribtue selectors for all elements, not just for the html tags lang attribute. For example html like <a title="Jeeha" href="foo.html">bar</a> could be selected like a[title=Jeeha] { ... } in css.
See this link for more details on partial matches and variants.

Resources