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

CssCss Selectors

Css Problem Overview


At W3Schools they declare both | and ^ to mean: Select an element with an attribute starting with a specified value.

So what's the difference?

Css Solutions


Solution 1 - Css

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>

Pipe (|): selects an element (<h1>) where the value of the specified attribute (rel) is either exactly the value (val) or starts with the value immediately followed by - (val-):

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

h1[rel|="friend"] { color: red; }

<h1 rel="friend-external-sandwich">I'm Red.</h1>
<h1 rel="friend2-external-sandwich">I'm Black.</h1>

More information about this selectors you can find here: https://css-tricks.com/attribute-selectors/ or on the official CSS specification: https://www.w3.org/TR/css3-selectors/#attribute-selectors

Solution 2 - Css

> As w3schools declare both | and ^ select attribute starting with a defined value

No, the | is not used to select elements whose attribute value start with a certain value.

Here is what the W3C Spec says about these selectors. (emphasis is mine)

>[att|=val] > > Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by "-" (U+002D). > >[att^=val] > > Represents an element with the att attribute whose value begins with the prefix "val". If "val" is the empty string then the selector does not represent anything.

So, the | symbol in the attribute selector would select only elements whose attribute value is either exactly the given value or starts with the given value followed by a hyphen.

As you can see in the below snippet, the attribute selector which uses | ([data-test |= 'val']) doesn't select the element when the attribute value is like valid whereas the attribute selector with ^ ([data-test ^= 'val']) does.

div[data-test |= 'val'] {
  color: beige;
}
div[data-test ^= 'val'] {
  background: red;
}

<div data-test='val'>Hello</div>
<div data-test='val-id'>Hello</div>
<div data-test='valid'>Hello</div>


In a more real-world scenario, the attribute selector with pipe (|) can be used to select elements and apply specific styling depending on their language (which can be set using the lang attribute). As we can see in the snippet, |= 'en' selects all elements whose lang attribute is either en or en-GB or en-US (or any other en-* for that matter).

As the spec states, the primary intention of this selector was to allow language subcode matches but as BoltClock points out, this has by and large been superseded by the :lang pseudo-class selector.

div[lang |= 'en']{
  font-size: 16px;
  background: steelblue;
}

div[lang |= 'zh']{
  font-size: 14px;
  background: mediumslateblue;
}

div{padding: 4px;}

<div lang='en'>English: The grass is green in colour.</div>
<div lang='en-GB'>English (UK): The grass is green in colour.</div>
<div lang='en-US'>English (US): The grass is green in color.</div>
<hr>
<div lang='zh-CN'>Chinese (Simplified): 草是绿色的。</div>
<div lang='zh-TW'>Chinese (Traditional): 草是綠色的。</div>

(Translations were by Google. Any mistake was unintentional)

Additional Information: The attribute selector which uses pipe (|) was introduced in CSS2 and the attribute selector which uses the cap/caret (^) was introduced in CSS3.

Solution 3 - Css

Simply put:

> E[foo|="en"] matches... > > an E element whose "foo" attribute has a hyphen-separated list of values beginning with "en" > > E[foo^="bar"] matches... > > an E element whose "foo" attribute value begins exactly with the string "bar"

Expanded Info:

> [att|=val] > > Represents an element with the att attribute, its value either being exactly "val" or beginning with "val" immediately followed by > "-". This is primarily intended to allow language subcode matches > (e.g., the hreflang attribute on the a element in HTML). > > [att^=val] > > Represents an element with the att attribute whose value begins with the prefix "val". If "val" is the empty string then the selector does > not represent anything.

Source: http://www.w3.org/TR/css3-selectors/#selectors


Examples

HTML

<ul>
    <li title="test">testing attribute selectors</li>
    <li title="testing">testing attribute selectors</li>
    <li title="testing test">testing attribute selectors</li>
    <li title="testing-test">testing attribute selectors</li>
    <li title="test-testing">testing attribute selectors</li>
</ul>

Testing the pipe (|) selector.

li[title|="testing"] { background-color: aqua; }

enter image description here

Testing the caret (^) selector.

li[title^="testing"] { background-color: pink; }

enter image description here

#pipe > li[title|="testing"] {
  background-color: aqua;
}
#caret > li[title^="testing"] {
  background-color: pink;
}

<p>
  <code>Testing the pipe (|) selector.</code>
</p>
<ul id="pipe">
  <li title="test">testing attribute selectors</li>
  <li title="testing">testing attribute selectors</li>
  <li title="testing test">testing attribute selectors</li>
  <li title="testing-test">testing attribute selectors</li>
  <li title="test-testing">testing attribute selectors</li>
</ul>

<hr>

<p>
  <code>Testing the caret (^) selector.</code>
</p>
<ul id="caret">
  <li title="test">testing attribute selectors</li>
  <li title="testing">testing attribute selectors</li>
  <li title="testing test">testing attribute selectors</li>
  <li title="testing-test">testing attribute selectors</li>
  <li title="test-testing">testing attribute selectors</li>
</ul>

jsFiddle

Solution 4 - Css

Actually

[attr ^= value] is value*
Caret (^) means starting with "value" (and obviously exact value as well)

[attr |= value] is value OR value-* (i.e. [attr = value],[attr ^= value-])
Pipe (|) means either exact "value" or starting with "value-" (succeeded by dash (-))

Example:

<!DOCTYPE html>
<html>
    <head>
        <style>
            /* [lang=en],[lang^=en-]*/
            [lang|=en] {
                background: cyan;
            }

            [lang^=ar] {
                background: lime;
            }
        </style>
    </head>
    <body>
        <p lang="en">Hello!</p>
        <p lang="en-us">Hi!</p>
        <p lang="en-gb">Ello!</p>
        <p lang="ens">Not me!</p>

        <p lang="ar">سلام</p>
        <p lang="ar-sa">السلام علیکم</p>
        <p lang="ar-ae">السلام علیکم و رحمۃ اللہ</p>
        <p lang="ars">Me as well</p>
    </body>
</html>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionalexView Question on Stackoverflow
Solution 1 - CssSebastian BroschView Answer on Stackoverflow
Solution 2 - CssHarryView Answer on Stackoverflow
Solution 3 - CssMichael BenjaminView Answer on Stackoverflow
Solution 4 - CssTalESidView Answer on Stackoverflow