CSS [attribute|=value] vs [attribute*=value] selectors - css

Why do we need the CSS [attribute|=value] Selector at all when the CSS3 [attribute*=value] Selector basically accomplishes the same thing, the browser compatibility is nearly similar? Is there something that the first CSS selector does and the second isn't able to? This is the first time to encounter two very similar selectors and wonder why the first one exists in the first place.

From the doc:
[attr|=value] Represents an element with an attribute name of attr.
Its value can be exactly “value” or can begin with “value” immediately
followed by “-” (U+002D). It can be used for language subcode matches.
[attr*=value] Represents an element with an attribute name of attr and
whose value contains at least one occurrence of string "value" as
substring.
Visual differences:
[attr|=value]
/* Any span in Chinese is red, matches simplified (zh-CN) or traditional (zh-TW) */
span[lang|="zh"] {color: red;}
<span lang='zh'>zh</span>
[attr*=value]
/* All links to with "example" in the url have a grey background */
a[href*="example"] {background-color: #CCCCCC;}
<a href="www.example.com">example<a/>
In the same code example:
div[color|="red"] {
background: red;
}
div[color*="blue"] {
color: blue;
}
<div>
<div color='red-yellow'>This shoud has only red background</div>
<div color='blue'>This shoud has only blue color</div>
<div color='red-blue'>This shoud has blue color and red background</div>
<div color='blue-red'>This shoud be only blue color</div>
</div>
References
Attribute selectors

There are a lot of differences between these two selectors
[lang|=en] {
background: yellow;
}
[lang*=en] {
color:red;
}
<p lang="en">Hello!</p>
<p lang="en-us">Hi!</p>
<p lang="en-gb">Ello!</p>
<p lang="usen">Hi!</p>
<p lang="noen">Hei!</p>
<p><b>Note:</b> For [<i>attribute</i>|=<i>value</i>] to work in IE8 and earlier, a DOCTYPE must be declared.</p>
The [attribute|=value] selector is used to select elements with the specified attribute starting with the specified value.
The [attribute*=value] selector matches every element whose attribute value containing a specified value.
See the example to get a clear idea about both the selectors.

They are distinctly different:
[attr|=value]
Represents an element with an attribute name of attr. Its value can be exactly “value” or can begin with “value” immediately followed by “-” (U+002D). It can be used for language subcode matches.
[attr*=value]
Represents an element with an attribute name of attr and whose value contains at least one occurrence of string "value" as substring.
https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

The first selector ensures the attribute value starts with the value submitted, the second only requires the attribute value contains it.
This would be helpful if you had to distinguish between attributes that had the same string in different positions within the same attribute.

CSS has evolved over time, and as it has evolved the need and want for more selectors, and functions has increased.
The CSS [attribute|=value] Selector was defined before CSS3 (latest version), and was available in CSS 2.1. As noted in the page you linked to:
used to select elements with the specified attribute starting with the specified value.
Whilst this is handy in most cases, sometimes there are frameworks, which come with structured css in the from of someString_somethingUseful_somethingElse for its class definition.
Now say I wanted to select all elements with the somethingUseful bit in it. The above selector would not allow me to do this, as the somethingUseful bit of the class definitions located in the middle of the class name. the same with the somethingElse bit, it is located at the end.
Thus in CSS3, we saw the introduction of [attribute*=value] selector which allows us to select elements which may have these keywords as a substring in their definition (though not necessarily at the front) See:
selector matches every element whose attribute value containing a specified value.

Related

Can a CSS selector search part of a word?

I need a pure CSS way to select an element based on part of an HTML attribute value. For example, I want to select this element:
<div data-gt="{'type':'select_me'}"></div>
based on the fact that the element has a data-gt value that contains select. The closest I can get is using [data-gt~=select] as a CSS selector, but that searches for whole words only. So if the word select in the HTML attribute was surrounded by spaces like {'type':' select _me'}, it could find it no problem, but it can't find it because it's preceded by a quote and followed by an underscore.
Note: The example above is a simplified version of what I want to do, so no I can't just change how the HTML attribute is generated and no I can't predict any of the surrounding data in the data-gt attribute.
Just curious if there is a pure CSS way to do this? I know it could be handled with Javascript, but that doesn't work for my purposes.
You can use the * attribute selector:
Represents elements with an attribute name of attr whose value
contains at least one occurrence of value within the string.
[data-gt*="select"] {
color: red;
}
<div data-gt="{'type':'select_me'}">Select Me</div>
<div data-gt="{'type':'please_dont'}">Don't Select Me</div>

What CSS selector is this? [ui-view].ng-enter-active

What CSS selector is the first part in square brackets?
[ui-view].ng-enter-active {}
It is not an attribute selector that would be this right?
ui-view[content] {}
It is indeed an attribute selector. An attribute selector and a class selector are both simple selectors, and simple selectors in a sequence may be arranged in any order, with the exception that a type or universal selector, if present, must come first.
This means [ui-view].ng-enter-active and .ng-enter-active[ui-view] are both valid and equivalent, matching an element that has a class "ng-enter-active" as well as an attribute named "ui-view". The former seems strange at first only because you rarely see attribute selectors appearing first in a simple selector sequence.
Your second example, ui-view[content], contains a type selector, ui-view. Because of this, unlike your first example, it cannot be rewritten as [content]ui-view, since, as mentioned, type selectors must come first.
That is an attribute selector. It would select an element that has both a ui-view attribute as well as the class ng-enter-active. That attribute selector doesn't care about the actual value of the attribute. So for example, it would correctly select the following:
<div ui-view class="ng-enter-active"></div>
as well as:
<div ui-view="valueDoesntMatter" class="ng-enter-active"></div>
It's attribute selector, so:
The first one
[ui-view].ng-enter-active
means element with class ng-enter-active and attribute ui-view, eg.
<div class="ng-enter-active" ui-view="abc">
<div class="ng-enter-active" ui-view> <!-- or with attribute without value -->
The second one,
ui-view[content]
means element ui-view (you probably forgot dot, class="ui-view") with attribute content
<ui-view content="abc">
OR probably, if you forgot . in selector
<div class="ui-view" content="whatever">
See more about attribute selector: http://quirksmode.org/css/selectors/selector_attribute.html

How To Apply CSS rule to Classes with Specific Keywords Inside Them?

That is to say, see the following:
<div class="helloeverybody">
</div>
<div class="heyeveryperson">
</div>
I want to apply a css rule to every class with the word "every" in it.
Is there a formal name for this?
You can use the "contains" attribute selector by appending an asterisk after the attribute - e.g.
div[class*=every] {
color: orange;
}
http://jsfiddle.net/FWP8j/1/
The definition from Selectors Level 3:
Represents an element with the att attribute whose value contains at
least one instance of the substring "val". If "val" is the empty
string then the selector does not represent anything.

How do I target elements with an attribute that has any value in CSS?

I know that I can target elements which have a specific attribute in CSS, for example:
input[type=text]
{
font-family: Consolas;
}
But is it possible to target elements which have an attribute of any value (except nothing i.e. when the attribute hasn't been added to the element)?
Roughly something like:
a[rel=*]
{
color: red;
}
Which should target the first and third <a> tags in this HTML:
red text
standard text
red text again
I figure it's possible because by default, cursor: pointer seems to be applied to any <a> tag which has a value for its href attribute.
The following will match any anchor tag with a rel attribute defined:
a[rel]
{
color: red;
}
http://www.w3.org/TR/CSS2/selector.html#pattern-matching
Update:
To account for the scenario #vsync mentioned, in the comment section (differentiating between emtpy/non-empty values), you could incorporate the CSS :not pseudo-class:
a[rel]:not([rel=""])
{
color: red;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/:not
Yes in CSS 3 selectors there are several attribute selectors.
E.g.
[att]
Represents an element with the att attribute, whatever the value of the attribute.
[att=val]
Represents an element with the att attribute whose value is exactly "val".
[att~=val]
Represents an element with the att attribute whose value is a whitespace-separated list of words, one of which is exactly "val". If
"val" contains whitespace, it will never represent anything (since the
words are separated by spaces). Also if "val" is the empty string, it
will never represent anything.
[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.
[att$=val]
Represents an element with the att attribute whose value ends with the suffix "val". If "val" is the empty string then the selector does
not represent anything.
[att*=val]
Represents an element with the att attribute whose value contains at least one instance of the substring "val". If "val" is the empty
string then the selector does not represent anything.
Should add that if a browser sets an attribute by default you may need to work around. This does not appear to be an issue in "modern" brosers, however, this is an issue I have seen, so be sure to check cross-browser performance.
For instance, I discovered that in IE prior to 9, colSpan is set for all TD's in a Table, so any single cell has the hidden colspan value of 1.
So if you were targetting "any TD with colspan attribute" you apply in your webdoc, even the td's having no colspan attribute set, such as any TD being a single cell, will receive the css styling. IE less than 9 will basically style them all!
Only reason to concern over this is all the remaining XP users out there who cannot upgrade above IE8.
So for Example, I have a group of tables where the content may shift from end to end, leaving anywhere from 1 to 7 cells blank either at the end or the beginning.
I want to apply a color to any blank cells at the end or the beginning utilizing the colspan attribute.
Using the following will not work in IE less than 9
#my td[colspan] {background-color:blue;}
...all TD's will get styled (funny since the conditional attribute styling was supposedly superior in IE, but I digress...).
Using the following works across all browsers when I set the value of colspan to 'single' for any solitary cell/TD I wish to include in the styling scheme, however its a 'hack' and will not properly validate...
#my td[colspan="single"] {background-color:blue;} /* 'single' could be anything */
#my td[colspan="2"] {background-color:blue;}
#my td[colspan="3"] {background-color:blue;}
#my td[colspan="4"] {background-color:blue;}
#my td[colspan="5"] {background-color:blue;}
#my td[colspan="6"] {background-color:blue;}
#my td[colspan="7"] {background-color:blue;}
Alternatively you should be able to more appropriately address the issue using conditional styling using "if lt IE 9" to override. It would be the correct way to do this, just keep in mind you must hide the "properly constructed css" from IElt9 in the process, and I think the only proper way to do that is with selective style sheets.
Most of us already do that anyway, but regardless, you still do well to consider and test if a browser applies an auto-attribute when it sees none, and how it may handle your otherwise corect syntax for styling on attribute values.
(btw, colspan just happens not to be in the css specification yet [as of css3], so this example throws no validation error.)

Is there a CSS selector by class prefix?

I want to apply a CSS rule to any element whose one of the classes matches specified prefix.
E.g. I want a rule that will apply to div that has class that starts with status- (A and C, but not B in following snippet):
<div id='A' class='foo-class status-important bar-class'></div>
<div id='B' class='foo-class bar-class'></div>
<div id='C' class='foo-class status-low-priority bar-class'></div>
Some sort of combination of:
div[class|=status] and div[class~=status-]
Is it doable under CSS 2.1? Is it doable under any CSS spec?
Note: I do know I can use jQuery to emulate that.
It's not doable with CSS2.1, but it is possible with CSS3 attribute substring-matching selectors (which are supported in IE7+):
div[class^="status-"], div[class*=" status-"]
Notice the space character in the second attribute selector. This picks up div elements whose class attribute meets either of these conditions:
[class^="status-"] — starts with "status-"
[class*=" status-"] — contains the substring "status-" occurring directly after a space character. Class names are separated by whitespace per the HTML spec, hence the significant space character. This checks any other classes after the first if multiple classes are specified, and adds a bonus of checking the first class in case the attribute value is space-padded (which can happen with some applications that output class attributes dynamically).
Naturally, this also works in jQuery, as demonstrated here.
The reason you need to combine two attribute selectors as described above is because an attribute selector such as [class*="status-"] will match the following element, which may be undesirable:
<div id='D' class='foo-class foo-status-bar bar-class'></div>
If you can ensure that such a scenario will never happen, then you are free to use such a selector for the sake of simplicity. However, the combination above is much more robust.
If you have control over the HTML source or the application generating the markup, it may be simpler to just make the status- prefix its own status class instead as Gumbo suggests.
CSS Attribute selectors will allow you to check attributes for a string. (in this case - a class-name)
https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
(looks like it's actually at 'recommendation' status for 2.1 and 3)
Here's an outline of how I *think it works:
[ ] : is the container for complex selectors if you will...
class : 'class' is the attribute you are looking at in this case.
* : modifier(if any): in this case - "wildcard" indicates you're looking for ANY match.
test- : the value (assuming there is one) of the attribute - that contains the string "test-" (which could be anything)
So, for example:
[class*='test-'] {
color: red;
}
You could be more specific if you have good reason, with the element too
ul[class*='test-'] > li { ... }
I've tried to find edge cases, but I see no need to use a combination of ^ and * - as * gets everything...
example: http://codepen.io/sheriffderek/pen/MaaBwp
http://caniuse.com/#feat=css-sel2
Everything above IE6 will happily obey. : )
note that:
[class] { ... }
Will select anything with a class...
This is not possible with CSS selectors. But you could use two classes instead of one, e.g. status and important instead of status-important.
You can't do this no. There is one attribute selector that matches exactly or partial until a - sign, but it wouldn't work here because you have multiple attributes. If the class name you are looking for would always be first, you could do this:
<html>
<head>
<title>Test Page</title>
<style type="text/css">
div[class|=status] { background-color:red; }
</style>
</head>
<body>
<div id='A' class='status-important bar-class'>A</div>
<div id='B' class='bar-class'>B</div>
<div id='C' class='status-low-priority bar-class'>C</div>
</body>
</html>
Note that this is just to point out which CSS attribute selector is the closest, it is not recommended to assume class names will always be in front since javascript could manipulate the attribute.

Resources