This question already has answers here:
What is the ::content/::slotted pseudo-element and how does it work?
(2 answers)
Closed 5 months ago.
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
The CSS ::slotted selector selects children of the <slot> element.
However, when trying to select grandchildren like with ::slotted(*), ::slotted(*) *, or ::slotted(* *), the selector doesn't seem to take effect.
class MyElement extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({mode: 'open'})
shadowRoot.innerHTML = `
<style>
::slotted(*) {
display: block;
border: solid blue 1px;
padding: 3px;
}
::slotted(*) span {
display: block;
border: solid red 1px;
padding: 3px;
}
::slotted(* span) {
display: block;
border: solid green 1px;
padding: 3px;
}
</style>
<slot></slot>
`;
}
}
customElements.define('my-element', MyElement);
<my-element>
<p>
<span>Test</span>
</p>
</my-element>
Note how the span doesn't get the border.
Is this expected behavior? I wasn't able to find concrete documentation for this.
If yes, is there a way to work around this?
styling ::slotted elements in shadowDOM
TL;DR
::slotted Specs: https://drafts.csswg.org/css-scoping/#slotted-pseudo
slotted content remains in light DOM, is reflected to a <slot> in shadow DOM
::slotted(x) targets the lightDOM outer-Element (aka 'skin'), NOT the SLOT in shadowDOM
::slotted(x) takes basic selectors
Inheritable styles trickle into shadowDOM
https://lamplightdev.com/blog/2019/03/26/why-is-my-web-component-inheriting-styles/
For the latest WHATWG discussion on SLOT and related topics, see
https://github.com/whatwg/html/issues/6051#issuecomment-816971072
Participants: rniwa (Apple) , annvk (Mozilla), dominic (Google)
https://github.com/WICG/webcomponents/issues/934#issuecomment-906063140
Interesting reads:
A history of the HTML <slot> element by Jan Miksovsky
Summary of positions on contentious bits of Shadow DOM — Web Components F2F on 2015-04-24
background
Yes, ::slotted() not styling nested elements is expected behavior.
The term slotted is counterintuitive,
it implies element lightDOM is moved to shadowDOM
slotted lightDOM is NOT moved, it remains.. hidden.. in lightDOM
the content (IF slotted) is reflected to a <slot></slot>
Or from Google Developer Documentation
𝘾𝙤𝙣𝙘𝙚𝙥𝙩𝙪𝙖𝙡𝙡𝙮, 𝙙𝙞𝙨𝙩𝙧𝙞𝙗𝙪𝙩𝙚𝙙 𝙣𝙤𝙙𝙚𝙨 𝙘𝙖𝙣 𝙨𝙚𝙚𝙢 𝙖 𝙗𝙞𝙩 𝙗𝙞𝙯𝙖𝙧𝙧𝙚.
𝙎𝙡𝙤𝙩𝙨 𝙙𝙤𝙣'𝙩 𝙥𝙝𝙮𝙨𝙞𝙘𝙖𝙡𝙡𝙮 𝙢𝙤𝙫𝙚 𝘿𝙊𝙈; 𝙩𝙝𝙚𝙮 𝙧𝙚𝙣𝙙𝙚𝙧 𝙞𝙩 𝙖𝙩 𝙖𝙣𝙤𝙩𝙝𝙚𝙧 𝙡𝙤𝙘𝙖𝙩𝙞𝙤𝙣 𝙞𝙣𝙨𝙞𝙙𝙚 𝙩𝙝𝙚 𝙨𝙝𝙖𝙙𝙤𝙬 𝘿𝙊𝙈.
I use the term reflected instead of render because render implies you can access it in shadowDOM.
You can not, because slotted content isn't in shadowDOM... only reflected from lightDOM.
Why :slotted has limited functionality
More advanced shadowDOM styling was tried.
WebComponents version 0 (v0) had <content> and ::content; but it was removed from the spec:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/content
The main takeway from the W3C standards discussions
(#hayatoito (Google team) here and here) is:
So in V1 we have :slotted: https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
Addition #1 : Performance if ::slotted allowed for complex selectors
From Mozilla developer Emilio:
source: https://github.com/w3c/webcomponents/issues/889
The performance issue is that it increments the amount of subtrees in
which every node needs to go look for rules that affect to them.
Right now the logic goes like: if you're slotted, traverse your slots
and collect rules in their shadow trees as needed. This is the code
This is nice because the complexity of styling the element
depends directly on the complexity of the shadow trees that you're
building, and it only affects slotted nodes.
If you want to allow combinators past slotted then every node would
need to look at its ancestor and prev-sibling chain and look at which
ones of them are slotted, then do that process for all their slots.
Then, on top, you also need to change the general selector-matching
code so that selectors that do not contain slotted selectors don't
match if you're not in the right shadow tree.
That's a cost that you pay for all elements, regardless of whether you
use Shadow DOM or ::slotted, and is probably just not going to fly.
So due to performance issues
:slotted( S ) got limited CSS selector functionality:
► it only takes simple selectors for S. --> Basically anything with a space won't work
► it only targets lightDOM 'skin'. --> In other words, only the first level
<my-element>
<h1>Hello World</h1>
<p class=foo>
<span>....</span>
</p>
<p class=bar>
<span>....</span>
</p>
</my-element>
::slotted(h1) and ::slotted(p) works
::slotted(.foo) works
::slotted(span) (or anything deeper) will not work (not a 'skin' element)
Note: ::slotted([Simple Selector]) confirms to Specificity rules,
but (being simple) does not add weight to lightDOM skin selectors, so never gets higher Specificity.
You might need !important in some (rare) use cases.
<style>
::slotted(H1) {
color: blue !important;
}
<style>
Styling slotted content
Also see: Applying more in depth selection to the :host CSS pseudo class
#1 - style lightDOM
The <span> is hidden in lightDOM, any changes made there will continue to reflect to its slotted representation.
That means you can apply any styling you want with CSS in the main DOM
(or a parent shadowDOM container if you wrapped <my-element> in one)
<style>
my-element span {
.. any CSS you want
}
<style>
#2 - (workaround) move lightDOM to shadowDOM
If you move lightDOM to shadowDOM with: this.shadowRoot.append(...this.childNodes)
you can do all styling you want in a shadowDOM <style> tag.
Note: You can not use <slot></slot> and :slotted() anymore now.
<slot>s only works with content reflected from lightDOM.
For an example where an element wraps itself in an extra shadowDOM layer,
so no CSS bleeds out, and <slot>s can be used, see:
https://jsfiddle.net/WebComponents/5w3o2q4t/?slotmeister
#3 - ::part (shadow Parts)
It is a different/powerful way of styling shadowDOM content:
Apple finally implemented shadowParts in Safari 13.1, March 2020
see:
https://meowni.ca/posts/part-theme-explainer/
https://css-tricks.com/styling-in-the-shadow-dom-with-css-shadow-parts/
https://dev.to/webpadawan/css-shadow-parts-are-coming-mi5
https://caniuse.com/mdn-html_global_attributes_exportparts
Note! ::part styles shadowDOM,
<slot></slot> content remains in lightDOM!
references
be aware: might contain v0 documentation!
https://css-tricks.com/encapsulating-style-and-structure-with-shadow-dom/
https://developers.google.com/web/fundamentals/web-components/shadowdom?hl=en#composition_slot
https://polymer-library.polymer-project.org/2.0/docs/devguide/style-shadow-dom#style-your-elements
https://github.com/w3c/webcomponents/issues/331
https://github.com/w3c/webcomponents/issues/745
https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/slotchange_event
::part() - https://developer.mozilla.org/en-US/docs/Web/CSS/::part
Example: Using slots as a router
Change the slot-name on buttonclick and reflect content from lightDOM:
<template id=MY-ELEMENT>
<style>
::slotted([slot="Awesome"]){
background:lightgreen
}
</style>
<slot><!-- all unslotted content goes here --></slot>
<slot id=answer name=unanswered></slot>
</template>
<style>/* style all IMGs in lightDOM */
img { max-height: 165px;border:3px dashed green }
img:hover{ border-color:red }
</style>
<my-element><!-- content below is: lightDOM! -->
SLOTs are: <button>Cool</button> <button>Awesome</button> <button>Great</button>
<span slot=unanswered>?</span>
<div slot=Cool> <img src="https://i.imgur.com/VUOujQT.jpg"></div>
<span slot=Awesome><b>SUPER!</b></span>
<div slot=Awesome><img src="https://i.imgur.com/y95Jq5x.jpg"></div>
<div slot=Great> <img src="https://i.imgur.com/gUFZNQH.jpg"></div>
</my-element>
<script>
customElements.define('my-element', class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode:'open'})
.append(document.getElementById(this.nodeName).content.cloneNode(true));
this.onclick = (evt) => {
const label = evt.composedPath()[0].innerText; // Cool,Awesome,Great
this.shadowRoot.getElementById("answer").name = label;
}
}
});
</script>
Related
Let's assume that the user can add styles for every component in admin panel and I get it as string in my Node server:
const stylesFromAPI = ".p { color: red } .bg { background: lime }";
How to prefix this styles before append to my document to avoid conflicts?
I need something like CSS modules but working with strings (not as module loader):
const stylesFromAPI = css(".p { color: red } .bg { background: lime }"); // returns hashedClassname685946898456
<SomeCompontent className={stylesFromAPI} />
produces:
<style>
.hashedClassname685946898456 .p { color: red }
.hashedClassname685946898456 .bg { background: lime }
</style>
<div class="hashedClassname685946898456"></div>
Shadow DOM seems like a reasonable option here. You can create your style tags with inside the shadow DOM without having to deal with any selector prefixes. For example, using the react-shadow package:
import root from 'react-shadow';
Then in JSX, something like:
<root.div>
<style type="text/css">
{/* CSS string here */}
</style>
<div>
{/* Stuff here */}
</div>
</root.div>
Check out a working example of this here: https://github.com/joshdavenport/stack-overflow-61566764-react-css-shadow-dom
The main downside here is your styles from outside the shadow DOM will not apply. Those using the shadow DOM for components see this as a good thing, those simply trying to scope CSS do not. Not sure what it is you're scoping, so I can't really tell if that would be an issue for you.
If it is, you could re-import your styles within the shadow DOM, though I can't really point out how to do that without knowing what bundler is in use and how it is in use.
Alternatively you could pull apart your imported CSS using the css package, iterate over the selectors prefixing all with a randomly generated class, and then re-stringify.
I know CSS selector with the highest specificity takes precedence (i.e. .classname < #idname).
I also know that if things are the same specificity, then the last statement called takes precedence:
.classname1 { color: red; }
.classname1 { color: blue; } // classname1 color will be blue
Does the ordering of HTML classes on a DOM element affect the statement priority?
I have to disagree slightly with Jon and Watson's answers, as...
Yes, it Can (depending on the statement)
Your question is:
Does the ordering of CSS classes on a DOM element affect the statement priority?
Which does depend on the statement in question.
HTML Ordering Does Not Typically Matter
The following are equivalent when it comes to a straight call to a class (i.e. .class1 or .class2) or to a combined call (i.e. .class1.class2 or .class2.class1):
<div class="class1 class2"></div>
<div class="class2 class1"></div>
Cases Where Statement Priority for above HTML Can be Affected Based on HTML Order
The main place where ordering in HTML matters is with the use of attribute selectors in your CSS.
Example 1 Fiddle using the following code seeking to match attribute value will NOT have any change in font color, and each div will have different properties because of the ordering of the classes:
[class="class1"] {
color: red;
}
[class="class1 class2"] {
background-color: yellow;
}
[class="class2 class1"] {
border: 1px solid blue;
}
Example 2 Fiddle using the following code seeking to match beginning of attribute value will NOT have any change in font color for the second div, and each div will have different properties because of the ordering of the classes:
[class^="class1"] {
color: red;
}
[class^="class1 class2"] {
background-color: yellow;
}
[class^="class2 class1"] {
border: 1px solid blue;
}
Example 3 Fiddle using the following code seeking to match end of attribute value will NOT have any change in font color for the first div, and each div will have different properties because of the ordering of the classes:
[class$="class1"] {
color: red;
}
[class$="class1 class2"] {
background-color: yellow;
}
[class$="class2 class1"] {
border: 1px solid blue;
}
A Clarifying Statement about "Priority"
To be clear, in the cases above, what is affected as far as "statement priority" is concerned is really a matter of whether the statement actually applies or not to the element. But since the application or not is in a sense, the basic priority, and since the above are cases where such application is actually based on the ordering of the classes on the HTML Dom element (rather than the presence or absence of the class), I thought it worth adding this as an answer.
Possible Valid Use of Class Ordering?
This is a thought occurring to me, based on BoltClock's comment. Consider just two classes being used to style elements based on whatever factors are deemed critical to different styling. These two classes theoretically can replace the use of eleven different individual classes using the combination of attribute selectors (actually, as will be noted later, the possibilities are almost limitless with but a single class, but I'll discuss that in a moment since this post is about ordering of multiple classes). For these two classes we can style elements differently as follows:
Assuming these HTML Combinations
<div class="class1">Element 1</div>
<div class="class2">Element 2</div>
<div class="class1 class2">Element 3</div>
<div class="class2 class1">Element 4</div>
CSS Possibilities
/* simply has the class */
.class1 {} /* affects elements 1, 3, 4 */
.class2 {} /* affects elements 2-4 */
/* has only a single class */
[class="class1"] {} /* affects element 1 only */
[class="class2"] {} /* affects element 2 only */
/* simply has both classes */
.class1.class2 {} /* affects elements 3-4 */
/* has both classes, but in a particular order */
[class="class1 class2"] {} /* affects element 3 only */
[class="class2 class1"] {} /* affects element 4 only */
/* begins with a class */
[class^="class1"] {} /* affects elements 1 & 3 only */
[class^="class2"] {} /* affects elements 2 & 4 only */
/* ends with a class
NOTE: that with only two classes, this is the reverse of the above and is somewhat
superfluous; however, if a third class is introduced, then the beginning and ending
class combinations become more relevant.
*/
[class$="class1"] {} /* affects elements 2 & 4 only */
[class$="class2"] {} /* affects elements 1 & 3 only */
If I calculate right, 3 classes could give at least 40 combinations of selector options.
To clarify my note about "limitless" possibilities, given the right logic, a single class can potentially have imbedded in it code combinations that are looked for via the [attr*=value] syntax.
Is all this too complex to manage? Possibly. That may depend on the logic of exactly how it is implemented. The point I am trying to bring out is that it is possible with CSS3 to have ordering of classes be significant if one desired it and planned for it, and it might not be horribly wrong to be utilizing the power of CSS in that way.
No, it does not. The relevant part of the W3C standard makes no mention of the order of appearance for classes.
No, it does not, like you said, if two rules have the same specificity, the one that comes later in your CSS will be applied.
No. But if you want to make one of your declaration blocks to has more precedence (w/o many !importants) make its selector more specific.
For example, for a div:
div.classname1 { color: red; } /* classname1 color will be red (for `div`s) */
.classname1 { color: blue; }
What's missing or a little hard to find in other answers is this:
What matters is the order in which the browser reads/parses the class names
The class defined last will win
.a {
color: red;
}
.b {
color: blue;
}
<div class="a b">This text will be blue</div>
<div class="b a">This text will ALSO be blue</div>
Example comes from this source
May be affected by the order of your imports
Because if this you may need to pay attention to how you import CSS in your files.
For example in my JavaScript based project I have a component that I can pass extra classes to. In order for my own classes to overwrite styles of the classes of the component itself I need to first import the component I wish to style (which will import its own styles) and only then import my own styles:
//import the component first, which will import css
import {SomeComponent} from 'some-library/SomeComponent';
//And THEN our own styles
import './styles.css';
return <SomeComponent className={myClassName} />
Like this my buildprocess (Webpack) will put my own classes later in the CSS bundle than the components ones.
Can I apply an external stylesheet to a specific div/element with shadow-dom or via any other means? I've heard about shadow-dom and I believe it lets you constrain your styles, but that's about all I know.
Specifically, I want half the page to use bootstrap, and the other half to use MUI or something else. This is just to show how my library works nicely with different themes.
I don't want to modify the CSS in anyway to constrain it to a specific element, nor do I want to use iframes.
Yes, you can apply an external stysheet in a Shadow DOM using the #import url CSS rule.
div.attachShadow( { mode: 'open' } )
.innerHTML = `
<style>
#import url( './external-style.css' )
</style>
<!-- other elements -->`
NB: The #import rule must placed at the top of the <style> element.
You can then manipulate the Shadow DOM like a normal DOM:
div.shadowRoot.appendChild( firstSection.cloneNode( true ) )
If your content is already existing in the normal DOM, you can move it with appendChild(), duplicate it with cloneNode() as in the above example), or reveal it with the help of <slot> element:
div1.attachShadow( { mode: 'open' } )
div1.shadowRoot.innerHTML = `
<style>
:host { display: inline ; background: #cfc ; }
::slotted( span ) { color: red ; }
</style>
<slot></slot>`
<div id=div1>
<span>Hello</span> world
</div>
In the last case you'll need to use the ::slotted pseudo-element to change the style of the original DOM, so maybe you'll have to modify already existing stylesheet. The best solution depends on your use case.
Consider the w3schools example of the :target selector:
<!DOCTYPE html>
<html>
<head>
<style>
:target {
border: 2px solid #D4D4D4;
background-color: #e5eecc;
}
</style>
</head>
<body>
<h1>This is a heading</h1>
<p>Jump to New content 1</p>
<p>Jump to New content 2</p>
<p>Click on the links above and the :target selector highlight the current active HTML anchor.</p>
<p id="news1"><b>New content 1...</b></p>
<p id="news2"><b>New content 2...</b></p>
<p><b>Note:</b> Internet Explorer 8 and earlier versions do not support the :target selector.</p>
</body>
</html>
When you click on the anchor referencing another element it styles thep with the corresponding id.
I want the effect of :target but on hover instead. how is this done?
how do you style the thing that href points to in the page on hover?
if this is not possible. what is the best-performing javascript solution?
Because CSS selectors can only traverse from an earlier element to a later sibling, descendant or descendant of a sibling (and cannot select parent, or previous-sibling, elements), this cannot be done with CSS. As hovering the <a> to style the later :target-ed elements would first require traversing to the parent from the hovered-<a> element.
To do this with JavaScript, then, I'd suggest:
// a named function to toggle the highlighting of the
// targeted element:
function highlightTarget(event) {
// the 'event' is passed automagically from the
// addEventListener() method; as is the 'this'
// which is the element to which the event-handler
// (this function) was bound:
// using getAttribute() to get the value of the attribute,
// instead of 'this.href' which would get the absolute URL,
// replacing the leading '#' character with an empty string:
var id = this.getAttribute('href').replace(/^#/, ''),
// getting the element with that id:
target = document.getElementById(id);
switch (event.type) {
// if this is the mouseenter event we add the 'highlight'
// class-name:
case 'mouseenter':
target.classList.add('highlight');
break;
// on 'mouseleave' we remove the class-name:
case 'mouseleave':
target.classList.remove('highlight');
break;
}
}
// iterating over the NodeList returned by
// document.getElementsByTagName(), using
// Array.prototype.forEach():
Array.prototype.forEach.call(document.getElementsByTagName('a'), function(a) {
// if the href attribute (not property) begins with a '#':
if (a.getAttribute('href').indexOf('#') === 0) {
// we bind the highlightTarget function to handle
// both the 'mouseenter' and 'mouseleave' events:
a.addEventListener('mouseenter', highlightTarget);
a.addEventListener('mouseleave', highlightTarget);
}
});
.highlight {
background-color: red;
}
<h1>This is a heading</h1>
<p>Jump to New content 1
</p>
<p>Jump to New content 2
</p>
<p>Click on the links above and the :target selector highlight the current active HTML anchor.</p>
<p id="news1"><b>New content 1...</b>
</p>
<p id="news2"><b>New content 2...</b>
</p>
<p><b>Note:</b> Internet Explorer 8 and earlier versions do not support the :target selector.</p>
It is worth noting, though, that the CSS Selectors Module, Level 4, has a proposed solution, the reference-combinator, to address this:
The following example highlights an element when its is focused or hovered-over:
label:matches(:hover, :focus) /for/ input, /* association by "for" attribute */
label:matches(:hover, :focus):not([for]) input { /* association by containment */
box-shadow: yellow 0 0 10px;
}
Which suggests that the correct syntax (which, currently of course, does not work) may be:
a:matches(:hover) /href/ p {
background-color: red;
}
References:
CSS:
Reference combinator (E:matches(:hover) /href/ p).
JavaScript:
Array.prototype.forEach().
Element.getAttribute().
EventTarget.addEventListener().
Function.prototype.call().
Guide to JavaScript Regular Expressions.
String.prototype.indexOf().
String.prototype.replace().
switch () {...} operator.
For Info:
In CSS if link is ahead and adjacent to the target or target's parent, then you could do something similar:
[href="#news1"]:hover ~#news1,
[href="#news2"]:hover ~#news2{
border: 2px solid #D4D4D4;
background-color: #e5eecc;
}
<h1>This is a heading</h1>
Jump to New content 1
Jump to New content 2
<p>hover link and see target element highlight via <code>[href="#target] ~#target </code></p>
<p id="news1"><b>New content 1...</b></p>
<p id="news2"><b>New content 2...</b></p>
<p><b>Note:</b> links must be ahead and adjacent to target or parents target in order to work.</p>
To go further and understand ,See: http://www.w3.org/TR/css3-selectors/#attribute-representation
and notice those too : http://www.w3.org/TR/css3-selectors/#adjacent-sibling-combinators & http://www.w3.org/TR/css3-selectors/#general-sibling-combinators
I know CSS selector with the highest specificity takes precedence (i.e. .classname < #idname).
I also know that if things are the same specificity, then the last statement called takes precedence:
.classname1 { color: red; }
.classname1 { color: blue; } // classname1 color will be blue
Does the ordering of HTML classes on a DOM element affect the statement priority?
I have to disagree slightly with Jon and Watson's answers, as...
Yes, it Can (depending on the statement)
Your question is:
Does the ordering of CSS classes on a DOM element affect the statement priority?
Which does depend on the statement in question.
HTML Ordering Does Not Typically Matter
The following are equivalent when it comes to a straight call to a class (i.e. .class1 or .class2) or to a combined call (i.e. .class1.class2 or .class2.class1):
<div class="class1 class2"></div>
<div class="class2 class1"></div>
Cases Where Statement Priority for above HTML Can be Affected Based on HTML Order
The main place where ordering in HTML matters is with the use of attribute selectors in your CSS.
Example 1 Fiddle using the following code seeking to match attribute value will NOT have any change in font color, and each div will have different properties because of the ordering of the classes:
[class="class1"] {
color: red;
}
[class="class1 class2"] {
background-color: yellow;
}
[class="class2 class1"] {
border: 1px solid blue;
}
Example 2 Fiddle using the following code seeking to match beginning of attribute value will NOT have any change in font color for the second div, and each div will have different properties because of the ordering of the classes:
[class^="class1"] {
color: red;
}
[class^="class1 class2"] {
background-color: yellow;
}
[class^="class2 class1"] {
border: 1px solid blue;
}
Example 3 Fiddle using the following code seeking to match end of attribute value will NOT have any change in font color for the first div, and each div will have different properties because of the ordering of the classes:
[class$="class1"] {
color: red;
}
[class$="class1 class2"] {
background-color: yellow;
}
[class$="class2 class1"] {
border: 1px solid blue;
}
A Clarifying Statement about "Priority"
To be clear, in the cases above, what is affected as far as "statement priority" is concerned is really a matter of whether the statement actually applies or not to the element. But since the application or not is in a sense, the basic priority, and since the above are cases where such application is actually based on the ordering of the classes on the HTML Dom element (rather than the presence or absence of the class), I thought it worth adding this as an answer.
Possible Valid Use of Class Ordering?
This is a thought occurring to me, based on BoltClock's comment. Consider just two classes being used to style elements based on whatever factors are deemed critical to different styling. These two classes theoretically can replace the use of eleven different individual classes using the combination of attribute selectors (actually, as will be noted later, the possibilities are almost limitless with but a single class, but I'll discuss that in a moment since this post is about ordering of multiple classes). For these two classes we can style elements differently as follows:
Assuming these HTML Combinations
<div class="class1">Element 1</div>
<div class="class2">Element 2</div>
<div class="class1 class2">Element 3</div>
<div class="class2 class1">Element 4</div>
CSS Possibilities
/* simply has the class */
.class1 {} /* affects elements 1, 3, 4 */
.class2 {} /* affects elements 2-4 */
/* has only a single class */
[class="class1"] {} /* affects element 1 only */
[class="class2"] {} /* affects element 2 only */
/* simply has both classes */
.class1.class2 {} /* affects elements 3-4 */
/* has both classes, but in a particular order */
[class="class1 class2"] {} /* affects element 3 only */
[class="class2 class1"] {} /* affects element 4 only */
/* begins with a class */
[class^="class1"] {} /* affects elements 1 & 3 only */
[class^="class2"] {} /* affects elements 2 & 4 only */
/* ends with a class
NOTE: that with only two classes, this is the reverse of the above and is somewhat
superfluous; however, if a third class is introduced, then the beginning and ending
class combinations become more relevant.
*/
[class$="class1"] {} /* affects elements 2 & 4 only */
[class$="class2"] {} /* affects elements 1 & 3 only */
If I calculate right, 3 classes could give at least 40 combinations of selector options.
To clarify my note about "limitless" possibilities, given the right logic, a single class can potentially have imbedded in it code combinations that are looked for via the [attr*=value] syntax.
Is all this too complex to manage? Possibly. That may depend on the logic of exactly how it is implemented. The point I am trying to bring out is that it is possible with CSS3 to have ordering of classes be significant if one desired it and planned for it, and it might not be horribly wrong to be utilizing the power of CSS in that way.
No, it does not. The relevant part of the W3C standard makes no mention of the order of appearance for classes.
No, it does not, like you said, if two rules have the same specificity, the one that comes later in your CSS will be applied.
No. But if you want to make one of your declaration blocks to has more precedence (w/o many !importants) make its selector more specific.
For example, for a div:
div.classname1 { color: red; } /* classname1 color will be red (for `div`s) */
.classname1 { color: blue; }
What's missing or a little hard to find in other answers is this:
What matters is the order in which the browser reads/parses the class names
The class defined last will win
.a {
color: red;
}
.b {
color: blue;
}
<div class="a b">This text will be blue</div>
<div class="b a">This text will ALSO be blue</div>
Example comes from this source
May be affected by the order of your imports
Because if this you may need to pay attention to how you import CSS in your files.
For example in my JavaScript based project I have a component that I can pass extra classes to. In order for my own classes to overwrite styles of the classes of the component itself I need to first import the component I wish to style (which will import its own styles) and only then import my own styles:
//import the component first, which will import css
import {SomeComponent} from 'some-library/SomeComponent';
//And THEN our own styles
import './styles.css';
return <SomeComponent className={myClassName} />
Like this my buildprocess (Webpack) will put my own classes later in the CSS bundle than the components ones.