Are CSS selectors case-sensitive? - css

I was recently updating a CMS site and a tab-navigation plugin had inserted the following markup:
<li id="News_tab">...
I've always written my CSS selectors in lowercase so when I tried to style this with #news_tab, it wouldn't apply, but #News_tab worked.
After all these years I'm surprised that I haven't run into this before, so I've always been under the impression that CSS was case-insensitive. Has CSS always been case-sensitive and I just haven't noticed thanks to my consistent code style?

CSS itself is case insensitive, but selectors from HTML (class and id) are case sensitive:
CSS recommendation on case sensitivity
HTML recommendation, id attribute (note the [CS])

CSS4 (CSS Selector Level 4) adds support for case-insensitive match (ASCII only).
input[value='search' i]
It's the "i" at the end which would do the trick...
Check my other answer for details which browser supports this.

Class and ID attributes are case sensitive.

http://www.w3.org/TR/CSS2/syndata.html
All CSS syntax is case-insensitive within the ASCII range (i.e., [a-z] and [A-Z] are equivalent), except for parts that are not under the control of CSS
From the docs website.
Follow-up for selectors:
http://www.w3.org/TR/CSS2/selector.html
The case-sensitivity of document language element names in selectors depends on the document language. For example, in HTML, element names are case-insensitive, but in XML they are case-sensitive.

Related

CSS - attribute starts with selector?

I have HTML markup that contain randomly generated attributes from Angular. For example,
<i _ngcontent-sgg-c2 class="some-class"></i>
These attributes do not have values so I'm wondering in this case if I can use the [attribute^=value] attribute selector. Am I able to apply styles to all elements where the attributes themselves start with a certain pattern?
It's not possible to use wildcards on attributes names. See https://stackoverflow.com/a/21222776/3980303 where it was originally answered.
It seems though that the generated attribute of Angular is used for scoped styles.
Check this link for reference it explains that good https://dev.to/themeticulist/everything-you-should-know-about-styles-in-angular-12ab
Cheers.

How to use a pseudo-element to select links to domains ending in foo?

I am taking practice test for Microsoft 70-480. I came across the question in the image. To select attributes that end in specific given value should be a css attribute selector such as [attribute$='value']. I don't understand how we make that selection with a css pseudo-element. Can some one explain to me why
As you've correctly stated, you need an attribute selector for this (although you would need to use [attribute*=value] instead), and you can't match elements using pseudo-element selectors (that's why they're called pseudo-elements!).
The only explanation for the "correct answer" here being option C is that whoever wrote that test either made a mistake with the options, or doesn't understand CSS selectors. Hopefully the former.

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

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.

Why doesn't the selector h3:nth-child(1):contains('a') work?

I check this selector:
h3:nth-child(1):contains('a')
selector doesn't work?
I check this in firefinder and does return nothing (not info that there is zero elements)
Then check this:
h3:nth-child(1)
and it returns h3, so selector is almost good, but something with this(h3 has text 'a') text goes wrong.
:contains() is not was going to be a CSS3 selector (thanks T.J. Crowder for the link), but it didn't make it, most likely because the way it works tends to lead to severe performance and over-selection issues. For example, if an element E matches :contains() for a given string argument, then all of its ancestors would also match; using it with a universal selector would lead to unexpected results with certain style properties, on top of being slow for the browser.
There is no other CSS selector that serves a purpose like :contains(). So you'll have to find some other way, either by modifying your HTML or even by using jQuery's :contains(), to achieve the effect you want:
Select an h3 element
if it is the first child of its parent
and its text contains the letter 'a'.
For jQuery and Selenium RC users: :contains() is implemented in the Sizzle selector engine used by jQuery, which is also used in Selenium RC (but not Selenium WebDriver). It works as described in this decade-old revision of the CSS3 spec, but again, due to how the spec describes it, you need to use it with care or it may lead to unexpected selections.
On a final note, h3:nth-child(1) can be replaced with h3:first-child, which as a CSS2 selector has better browser support.
If you're trying to use :contains(a) to find an anchor tag (rather than the letter A), you could use:
h3:nth-child(1) a
or
h3:first-child a
The :contains() pseudo-class isn't in the CSS Spec and is not supported by either Firefox or Chrome.
You can find a couple of detailed discussion in:
selenium.common.exceptions.InvalidSelectorException with "span:contains('string')"
Finding link using text in CSS Selector is not working
Solution
As a solution you have to drop the contains() part and your effective locator will be:
h3:nth-child(1)
Further as #BoltClock mentioned within his answer, you can also use:
h3:first-child
As an alternative, you can also use:
h3:first-of-type
tl; dr
selenium.common.exceptions.InvalidSelectorException with "span:contains('string')"
Finding link using text in CSS Selector is not working

Resources