CSS Selector Clarification: |= VS ^=

CSS Selector Clarification: |= vs ^=

From the "real" reference (W3C):

E[foo^="bar"] an E element whose "foo" attribute value begins exactly with the string "bar"

E[foo|="en"] an E element whose "foo" attribute has a hyphen-separated list of values beginning (from the left) with "en"

Always go to the actual standard when there appears to be an inconsistency. I tend to avoid w3schools because their quality control is sometimes less than stellar.

What is the difference between | and ^ Selector?

You can check the difference by yourself. They both look for attribute values starting with some value. However, using |= you need the whole word (or the word separated by a hyphen - from the next word) to be selected. Example:

<h1 class="top-header">Welcome</h1>
<p class="top-text">Hello world!</p>
<p class="topcontent">Are you learning CSS?</p>

[class^="top"] will select the three of them.

[class|="top"] will select only the two first elements. The last <p> has the class topcontent and therefore the selector won't find the isolated word top

Difference between |= and ^= css

I think the official description in the w3c document says it all:

E[foo|="en"] - an E element whose foo attribute value is a hyphen-separated list of values beginning with en

E[foo^="bar"] - an E element whose foo attribute value begins exactly with the string "bar"

W3Schools documentation is imprecise at times, so for good documentation either go to MDN, or Sitepoint or use the official W3C Document.

Basically the |= selector matches words optionally immediately followed by a hyphen (- or U+002D respectively) and is useful with compound-classes and languages attributes.

<div class="wrapper-inner"><span lang="en-GB">...</span></div>

div[class|='wrapper']{/*...*/}
span[lang|='en']{/*...*/}

^= is a bit more general, basically a "substring match" and behaves exactly like ^ in a regex would.

You can see the difference of how the two selectors match in the following example:

*{
color:red;
/* now, if |= or ^= selector fails, the color is red */
}

[class|=en],[class^=de]{
color:green;
}
div::after{content:"FAIL"}
[class|=en]::after,[class^=de]::after{content:"pass"}
<div class="en-US">Case 1.1: |=en matching "en-US": </div>
<div class="en">Case 1.2: |=en matching "en": </div>
<div class="en-">Case 1.3: |=en matching "en-": </div>
<div class="en,">Case 1.4: |=en matching "en,": </div>
<div class="english">Case 1.5: |=en matching "english": </div>
<div class="en ">Case 1.6: |=en matching "en ": </div>
<div class="de-DE">Case 2.1: ^=de matching "de-DE": </div>
<div class="de">Case 2.2: ^=de matching "de": </div>
<div class="de ">Case 2.3: ^=de matching "de ": </div>
<div class="deutsch">Case 2.4: ^=de matching "deutsch": </div>

What is the difference between pipe (|) and caret (^) attribute selectors?

Caret (^): selects an element (<h1>) where the value of the specified attribute (rel) starts with a certain value (val):

h1[rel^="val"] { /** formatting */ }

h1[rel^="friend"] { color: blue; }
<h1 rel="friend-external-sandwich">I'm Blue.</h1><h1 rel="friend2-external-sandwich">I'm Blue.</h1><h1 rel="external-sandwich">I'm Black.</h1>

Is the CSS [attribute=value] Selector unnecessary?

The * in [class*='example'] is a selector that retrieves all elements that contains example in the class-name and not just elements with the class-name example.

So [class*='example'] will target all of the following:

<div class="iamanexample"></div>
<div class="example"></div>
<div class="whereisyourexample"></div>

Whereas .example or [class='example'] will only target the second element <div class="example"></div> from the above three.


Other attribute selectors in CSS includes the:

~ selector: This selector retrieves all elements whose targeted attribute's value contains the exact queried value. This selector can include multiple values in the form of a whitespace-separated list of words.

| selector: This selector retrieves all elements whose targeted attribute's value is exactly the queried value or begins with queried value immediately followed by a hyphen.

^ selector: This selector retrieves all elements whose targeted attribute's value starts with the queried value.

$ selector: This selector retrieves all elements whose targeted attribute's value ends with the queried value.


Check and run the following Code Snippet for a practical example and explanation in the code comments on how each of the above selector works:

/* all elements whose abc value contains "ment" */div[abc*="ment"] { font-weight: 700; }
/* all elements whose abc value is exactly "element-1" */div[abc~="element-1"] { color: blue; }
/* all elements whose abc value is exactly "element" or begins with "element" immediately followed by a hyphen */div[abc|="element"] { background-color: green; }
/* all elements whose abc value starts with "x" */div[abc^="x"] { background-color: red; }
/* all elements whose abc value ends with "x" */div[abc$="x"] { background-color: yellow; }
div { margin: 5px 0px; }
<div abc="element-1">Hello World!</div><div abc="element-2">Hello World!</div>
<div abc="xElement1">Hello World!</div><div abc="xElement2">Hello World!</div>
<div abc="element1x">Hello World!</div><div abc="element2x">Hello World!</div>

How exactly is [att~=val] different from [att*=val] in CSS Attribute Selectors?

From the JQuery help (which supports the standard selectors):

a[alt~="thumb"]

Description: Selects elements that have the specified attribute with a
value containing a given word, delimited by spaces. This selector
matches the test string against each word in the attribute value,
where a "word" is defined as a string delimited by whitespace. The
selector matches if the test string is exactly equal to any of the
words.

a[alt*="thumb"]

Description: Selects elements that have the specified attribute with a
value containing the a given substring. This is the most generous of
the jQuery attribute selectors that match against a value. It will
select an element if the selector's string appears anywhere within the
element's attribute value. Compare this selector with the Attribute
Contains Word selector (e.g. [attr~="word"]), which is more
appropriate in many cases.

Basically the selector ~= only matches if the value is found surrounded by white space. The selector *= matches if the value is found anywhere.

<div alt='heading navigation'>
<div alt='head'>

div[alt~='head'] would match only the second div, but div[alt*='head'] would match both.

Is there a CSS not equals selector?

In CSS3, you can use the :not() filter, but not all browsers fully support CSS3 yet, so be sure you know what you're doing which is now
supported by all major browsers (and has been for quite some time; this is an old answer...).

Example:

<input type="text" value="will be matched" />
<input type="text" value="will not be matched" class="avoidme" />
<input type="text" value="will be matched" />

and the CSS

input:not(.avoidme) { background-color: green; }

Note: this workaround shouldn't be necessary any more; I'm leaving it here for context.

If you don't want to use CSS3, you can set the style on all elements, and then reset it with a class.

input { background-color: green; }
input.avoidme { background-color: white; }

OR statement within CSS selector

As far as I can tell, there's no way to do what you're asking. In the CSS selector spec, the pipe character is used for something different when used with attribute selectors. It's used as a namespace separator.

Per the selector spec on the W3C:

The attribute name in an attribute selector is given as a CSS
qualified name: a namespace prefix that has been previously declared
may be prepended to the attribute name separated by the namespace
separator "vertical bar" (|). In keeping with the Namespaces in the
XML recommendation, default namespaces do not apply to attributes,
therefore attribute selectors without a namespace component apply only
to attributes that have no namespace (equivalent to "|attr"; these
attributes are said to be in the "per-element-type namespace
partition"). An asterisk may be used for the namespace prefix
indicating that the selector is to match all attribute names without
regard to the attribute's namespace.

CSS examples:

@namespace foo "http://www.example.com";
[foo|att=val] { color: blue }
[*|att] { color: yellow }
[|att] { color: green }
[att] { color: green }

The first rule will match only elements with the attribute att in the
"http://www.example.com" namespace with the value "val".

The second rule will match only elements with the attribute att
regardless of the namespace of the attribute (including no namespace).

The last two rules are equivalent and will match only elements with
the attribute att where the attribute is not in a namespace.

Source: http://www.w3.org/TR/selectors/#attrnmsp

Why are dashes preferred for CSS selectors / HTML attributes?

Code completion

Whether dash is interpreted as punctuation or as an opaque identifier depends on the editor of choice, I guess. However, as a personal preference, I favor being able to tab between each word in a CSS file and would find it annoying if they were separated with underscore and there were no stops.

Also, using hyphens allows you to take advantage of the |= attribute selector, which selects any element containing the text, optionally followed by a dash:

span[class|="em"] { font-style: italic; }

This would make the following HTML elements have italic font-style:

<span class="em">I'm italic</span>
<span class="em-strong">I'm italic too</span>

Ambiguity with arithmetic operator

I'd say that access to HTML elements via dot notation in JavaScript is a bug rather than a feature. It's a terrible construct from the early days of terrible JavaScript implementations and isn't really a great practice. For most of the stuff you do with JavaScript these days, you'd want to use CSS Selectors for fetching elements from the DOM anyway, which makes the whole dot notation rather useless. Which one would you prefer?

var firstName = $('#first-name');
var firstName = document.querySelector('#first-name');
var firstName = document.forms[0].first_name;

I find the two first options much more preferable, especially since '#first-name' can be replaced with a JavaScript variable and built dynamically. I also find them more pleasant on the eyes.

The fact that Sass enables arithmetic in its extensions to CSS doesn't really apply to CSS itself, but I do understand (and embrace) the fact that Sass follows the language style of CSS (except for the $ prefix of variables, which of course should have been @). If Sass documents are to look and feel like CSS documents, they need to follow the same style as CSS, which uses dash as a delimiter. In CSS3, arithmetic is limited to the calc function, which goes to show that in CSS itself, this isn't an issue.

Inconsistency with variable naming across languages

All languages, being markup languages, programming languages, styling languages or scripting languages, have their own style. You will find this within sub-languages of language groups like XML, where e.g. XSLT uses lower-case with hyphen delimiters and XML Schema uses camel-casing.

In general, you will find that adopting the style that feels and looks most "native" to the language you're writing in is better than trying to shoe-horn your own style into every different language. Since you can't avoid having to use native libraries and language constructs, your style will be "polluted" by the native style whether you like it or not, so it's pretty much futile to even try.

My advice is to not find a favorite style across languages, but instead make yourself at home within each language and learn to love all of its quirks. One of CSS' quirks is that keywords and identifiers are written in lowercase and separated by hyphens. Personally, I find this very visually appealing and think it fits in with the all-lowercase (although no-hyphen) HTML.



Related Topics



Leave a reply



Submit