I see that multiple attribute selectors are "and-ed" together for example:
/* Links that start with "https" and end in ".org" */
a[href^="https"][href$=".org"] {
color: green;
}
I there a way to express that I want to match all <a>s that have href containing one a, b or c?
Yes, you can target elements with one attribute value OR another in CSS.
Geat's selector list approach with commas , is the most straightforward, and also the most browser compatible:
a[href^="https"][href$=".org"][href*="a"],
a[href^="https"][href$=".org"][href*="b"],
a[href^="https"][href$=".org"][href*="c"] {
color: green;
}
https://a.org
https://b.org
https://c.org
https://d.org
http://a.org
I agree though that this can become cumbersome. Luckily we can use the modern CSS :is() pseudo class to shorten this selector:
a[href^="https"][href$=".org"]:is([href*="a"], [href*="b"], [href*="c"]) {
color: green;
}
https://a.org
https://b.org
https://c.org
https://d.org
http://a.org
This also has the benefit of making the selector list forgiving, where if one selector within :is() is invalid, the others will still work - a regular selector list in CSS is actually unforgiving and will break the entire list if one selector breaks!
Also note that both examples above will match A, B, C if they are contained within the protocol, path (any part of the URL) i.e.
a[href^="https"][href$=".org"]:is([href*="org"], [href*="http"], [href*="h"]) {
color: green;
}
https://org.org
https://s.org
https://x.org
https://y.org
http://website.org
Unfortunately, the substring syntax for attribute selectors in CSS does not currently feature a way to match A OR B in an elegant way like I've illustrated below which I'm sure is what you were hoping for:
a[href^="https"][href$=".org"][href*="a"|"b"|"c"]
Related
I have an unordered list with several list points in an HTML.
In my CSS, I want to target the 5th and 7th list points. So I go
.my-list li:nth-child(5, 7){
background:yellow;
}
Nothing. It only works with a single number. So I assume I cannot separate them with a comma. What character/symbol should I separate them with? Is this even possible? Alternative solution? I doubt that I need to rewrite a target for every single nth element in my list... We're nearly in 2022. Just my reasoning.
Given your specific example, it’s somewhat easier to select the 5th and 7the elements than “[rewriting the] the [selector] for every single nth element,” using :is():
.my-list li:is(:nth-child(5),:nth-child(7)) {
background:yellow;
}
But it remains a somewhat verbose alternative, in contrast to the approach you desire, which is, as yet, not possible.
If JavaScript was an option, then a simple utility function could retrieve the desired elements, but not in CSS alone as yet.
There is no symbol for that. You can separate them like this:
.my-list li:nth-child(5),
.my-list li:nth-child(7) {
background: yellow;
}
If you use css-preprocessors you can write it a little bit cleaner, especially if you'll give class for list item:
.item {
&:nth-child(5),
&:nth-child(7) {
background-color: #fff;
}
}
This question already has answers here:
Does the order of classes listed on an item affect the CSS?
(5 answers)
Closed 1 year ago.
If We do something like this in our css
.class01.class02.class03{ background-color: lavenderblush; }
.class03.class01.class02{ background-color: brown; }
and this in our html
<article class="class01 class02 class03"></article>
<article class="class03 class01 class02"></article>
the 2nd rule will be applied to both elements. Is there a way to make these rules apply according to the order?
It won't work because: Order of CSS classes in HTML doesn't matter but there is a way using attribute selector
article[class="class01 class02 class03"]{ background-color: lavenderblush; }
article[class="class03 class01 class02"]{ background-color: brown; }
<article class="class01 class02 class03">Test1</article>
<article class="class03 class01 class02">Test2</article>
You can use the [class="class1 class2 class3"] attribute in the css by specifying the order of classes you want.
article[class="class01 class02 class03"] {
background-color: lavenderblush;
}
article[class="class03 class01 class02"] {
background-color: brown;
}
<article class="class01 class02 class03">text</article>
<article class="class03 class01 class02">text</article>
Interesting question. I don't suggest doing it as classes aren't meant to be used like this, but I guess there's at least one way for accomplishing the desired result...
article {
width: 50px;
height: 50px;
}
article[class*="class01 class02 class03"] {
background: lavenderblush;
}
article[class*="class03 class01 class02"] {
background: brown
}
<article class="class01 class02 class03"></article>
<article class="class03 class01 class02"></article>
So we're checking that the class contains the exact provided substring, while the wildcard allows the class list to contain other classes before and after as well. When an exact match is needed we could use article[class="class03 class01 class02"].
The answer to the question is no: it is not possible to the normal common notation. Only the trick using the attribute selector as given in the other answers does work on the first look. But head up: it is not as easy as it seems.
EXPLANATION: HOW IT WORKS
Indeed you are able to calculate/controll it.
In HTML/CSS wins the element/class/id construct with highest specifity. It is a slightly complex ranking on the first view but if only used classes it is not as complicated.
For class construction a.b.c the specifity counts:
special combination off this three classes which overrides i.e. background setting of a.b.x
the total count of used classes what means this three classes overwrite i.e. background setting off a.b
NOTE ATTRIBUTE SELECTOR: One attribute selector counts as one class. So, if you have an attribute seletor [class="a b c"] it lose against c.b.a noted on another place in your stylesheet.
Order in HTML does not count for the specifity: a b c is the same combination and the same number of classes as c b a.
If a class construct (combination) with the same specifity noted twice in a CSS i.e. a.b.c: red and c.b.a: green the last notation overwrites the notation done before.
Some thinking:
Importand: the decision which concept is used to style a page is up to the coder himself!!! But even the attribute selector is a chance to realize that concept it is not the intendend way to use CSS. I asume using the rules of specifity in the intended css way could be a better/more intuitive way to control the design.
Links with information about specifity:
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
https://specifishity.com/
For the purpose of this demo, I'll use a StackOverflow element for credibility.
If you sign out of SO, you can see a large call to action box at the top of the page. Even easier, just go to their new Portuguese version here - https://pt.stackoverflow.com/
Once you see the call to action box (captured below) go ahead and inspect it with developer tools.
On the div with the ID of hero-content, you will notice a style that I have pasted below:
#herobox #hero-content {
background: #fff7d8;
border: none;
}
I have done some research and as we all know, div ID's should be unique to the page. Although, if they are unique, why would a selector need to state an ID within an ID?
There are a couple of reasons.
Stylesheets can be reused between HTML documents. You may wish to distinguish between #hero-content that is a descendant of #herobox one page and of #somethingelse on another page.
The more likely one in this case is specificity. Assuming, for example, that #hero-content is a <div>, a general rule to set the styling of #herobox div would be more specific that #herobox #hero-content. Adding an extra id selector would increase the specificity.
It might be simply to increase the specificity of that selector.
For example, the author may have wanted to override...
#hero-content { border: 2px solid #333; }
It could also be a side effect of a tool like LESS, where the author may have originally written...
#herobox {
// Lots of other CSS.
#hero-content {
// ...
}
// Lots of other CSS.
}
Consider the following HTML markup:
<input id="foo" class="bar" name="baz">
Are the following selectors equal (or even valid):
CSS
input#foo.bar[name=baz] { }
input.bar#foo[name=baz] { }
input[name=baz].bar#foo { }
/* etc */
And is it possible to move the element name to, say, end?
Edit: I know what specificity is, I want to know in which order the tag, id, class and attributes need to be specified.
They are all valid, as they comply with the syntax of sequence of simple selectors. They are equivalent, since their meaning, including specificity, are defined in a manner that does not depend on the order of the components.
It is not possible to move the element name (type selector) to the end, for purely syntactic reasons. The spec says that a simple selector “always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence”. This is to be interpreted so that the type selector, if present, must appear first. This is natural since there would be no way to distinguish it from e.g. a preceding class selector (a space could not be used since it has a quite special meaning in CSS selector syntax: .bar input is a valid selector and means something quite different from input.bar).
Please refer the answer of #Jukka as OP seemed to have changed the meaning of the question by minor edit, but if anyone's interested in specificity question before edit, than please read ahead.
First of all, neither of the selectors make sense, to be true, they are over specific.
Your selector holds an id which will be unique, so defining class as well as attr=val is not required
(If you are not using the same id for other element in some OTHER document..)
If for some case, you need them, say to override, like... (makes sense)
input#foo.bar[name=baz] {
/* More specificity overrides the selector below */
}
input[name=baz] {
/* Styles here */
}
Are the following selectors equal - YES, they are equal as far as the specficity goes, they all return a score of 121
Credits
(or even valid) - Completely Valid
Does order of tag(Not relevant), id, class - NO, whatever the order of attributes are, it doesn't matter.
BUT
The order of your CSS declaration block in the stylesheet matters, the last selector will override common properties as all the three selectors have equal specificity.
Demo (All three will render green text, regardless of the order of their attributes, but if you shuffle the CSS selectors block, the last one will override the common properties of previous two selectors - unless you define !important in one of the selector properties)
And is it possible to move the element name(Attribute) to, say, end? - YES
Pros & Cons —
All the selectors are overspecific
Bad as far as performance goes
Using attr=val selector, you are assuming that the value of the name attribute won't change, if it does, you will have to change your selectors as well.
P.S : Have an habit of quoting the attribute values.
Those are all legal:
<input type-"text" id="foo" class="bar" name="baz">
input#foo.bar[name=baz] { border:1px solid blue; }
input.bar#foo[name=baz] { border:1px solid red; }
input[name=baz].bar#foo { border:1px solid green; }
http://jsfiddle.net/hGj5B/
Remove the various style blocks and note that each selector will select the textbox.
By "equal", if you are asking is they have equivalent specificity, then the answer is yes given each selector has the same amount of elements, classes, attribute selectors, and ids. Since they are all equal, the order of the blocks in your stylesheet will serve to determine which conflicting styles will win out.
You cannot move the element to the end, as the other segments of the selector describe it by coming after.
Yes all of them are legal , But while execution the Later one Will over ride the Earlier Declarations,but some exceptions are there
check the Flow exceptions Here
input[name=baz].bar#foo { border:1px solid green; }
input.bar#foo[name=baz] { border:1px solid red; }
input#foo.bar[name=baz] { border:1px solid blue; }
input { border:1px solid #000000; }
http://jsfiddle.net/hGj5B/
for More Details Refer this Question..
The sequence of execution of CSS
I am trying to change the font for the whole page in HTML. By whole I mean everything: buttons, forms, etc. Is there a way to do this in CSS?
html {
color: green;
}
This would make the text green, but not the text of buttons.
Well, there's universal selector:
* {
color: green;
}
Take note, though, that specificity of this selector is the lowest (MDN).
Wild card selector
* {
color: green;
}
It may be the case that you need to over ride inline CSS and javascript generated CSS. In this case use !important as well
* {
color: green !important;
}
Use the * universal CSS selector.
The universal selector matches any element type. It can be implied (and therefore omitted) if it isn’t the only component of the simple selector.
The selector div * will match the following em elements:
"Universal" in the h1 element ( matches the <h1> )
"emphasize" in the p element ( matches the <p> )
"not” in the first li element (matches the <ul> or the <li>)
"type” in the second li element (matches the <ul> or the <li>)
Example:
This rule set will be applied to every element in a document:
* {
color: green;
}
Also to add, it's compatible with most browsers, although it can be buggy in Internet Explorer 5.5, 6.0, 7.0.
If you don't need to support IE < 8, and want something that's less smelly, set an explicit color only on html and force everything else to inherit the color. Colors are already inherited by default on most elements, but not all of them.
Since this means applying two different color declarations, you will need two separate rules:
html {
color: green;
}
body * {
color: inherit !important;
}
Honestly, you shouldn't rely on a wildcard selector for doing this. You should take advantage of CSS's native inheritance. The best thing to do would be to remove the specific color declarations from your stylesheet (as needed) and add the color to your body or html tag. Using a wildcard is similar to this, except you are declaring that every single element should have the CSS as apposed to the native inheritance.