How do CSS custom properties cascade? - html

Let's say I have following CSS :
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
and my markup is :
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
While I got red set directly on me!
<p>I’m red too, because of inheritance!</p>
</div>
My question is Does the CSS above translate to :
body {
color: blue;
}
div {
color: green;
}
#alert{
color: red;
}
or is there an additional
* {
color: red;
}
Without variables the universal selector applies the same CSS on all elements. Does this change and the styling becomes dependent on elements?
One more question I have is if :root translates to body in CSS.
Here is a CodePen demo : http://codepen.io/anon/pen/RrvLJQ

As you've correctly stated in your title, custom properties cascade. In fact, this is why the module is called CSS Custom Properties for Cascading Variables. That means your custom property --color is evaluated as-is per element, just as with any other CSS property. In terms of the actual styles that are applied to your elements, what you really only have is:
* {
color: var(--color);
}
The var(--color) value is then evaluated for each element based on how the --color property cascades. So it follows that:
The body element has a blue foreground.
Any div elements have a green foreground.
The element whose ID is "alert" has a red foreground.
Because you don't have a --color definition for *, it's inherited by default. Therefore all other elements inherit --color from their parent element: body > p inherits from body, becoming blue, and #alert > p inherits from #alert, becoming red.
If you really do want to express the cascaded values in terms of CSS, you could say that it translates to the following:
:root {
color: blue;
}
div {
color: green;
}
#alert {
color: red;
}
* {
color: inherit;
}
But only because the original CSS contains an explicit * { color: var(--color); } definition which ensures that every element's color maps to --color.
Note also that the code that you have comes from an example within the spec, which itself is described as follows:
If a custom property is declared multiple times, the standard cascade rules help resolve it. Variables always draw from the computed value of the associated custom property on the same element
One more question I have is if :root translates to body in CSS.
:root doesn't translate to any element in CSS, because CSS is document language-agnostic.
:root doesn't translate to body in HTML; it corresponds to html.

Related

Change style of content depending on another css property value

Say, I want to change the background color of all the content in a paragraph that does not have any text-decoration (like bold, underline, etc.). Is it possible to do it just using CSS with a some kind of syntax like this?
p[text-decoration=none] {
background-color: yellow;
}
A sample HTML content that this CSS should be applied will be something like this:
<p class="special">Yellow background <b>default background for paragraph</b> yellow
again <i>default</i> once again yellow.</p>
Requirements for the above to work:
Do not add style and/or class attributes to the paragraph contents, i.e., to <b>, <i>, etc.
Do not change the styles for <b>, <i>, etc.
Background-color should be specified for any content (HTML or CSS-style based) that does not have any text-decoration.
The parent of <p> may have a custom background-color, so elements like <b> or <i> should assume that color.
It is impossible to make the absolutely correct decision according to your requirements with the help of CSS. But you can apply a little trick, which is to use the CSS variables declared inside :root.
The principle is to use the same background color for the background of the main parent and the background of tags b and i. You need to declare a variable like this:
:root {
--backColor: yellowgreen;
}
Next, using function var(), assign the declared variable for rules background-color, body tags (parent), b and i:
background-color: var(--backColor);
In pseudo-class :is(), you need to specify tags (b and i) for which the background color of the variable will be assigned.
:root {
--backColor: yellowgreen;
}
body {
background-color: var(--backColor);
}
p {
background-color: yellow;
display: inline-block;
}
p * {
display: inherit;
}
p *:is(b, i) {
background-color: var(--backColor);
}
<p class="special">Yellow background <b>default background for paragraph</b> yellow again <i>default</i> once again yellow.</p>

CSS :not selector being ignored

So I have a div with class='content' and inside that, another div with attribute style='background-color:#FF0000' so my code looks like the following:
<div class='content'>
Here is some text outside the red background div
<div style='background-color:#FF0000'>
Here is some text inside the red background div
</div>
</div>
And in my stylesheet I have the following:
[style^='background'] {
color:#00FF00
}
This works and I get green text inside the red background. However:
:not([style^='background']) {
color:#00FF00
}
This still makes the red background text green, along with everything else in the document. I have tried the following:
div:not([style^='background']) {
color:#00FF00
}
.content :not([style^='background']) {
color:#00FF00
}
:not([style]) {
color:#00FF00
}
Yet all of these make the red-background text green, when clearly I have the :not selector.
However, I have elsewhere:
.content div:not([style^='text-align']) {
color:#1f1f1f;
}
.content div :not(span[style^='font-size: 150%']) {
color:#EEE;
}
And these work just fine.
So I don't understand why the red background div won't work at all and is selected by the :not selector?
Example:
:not(.content) {
color:#FF0000
}
<div class='content'>
Here is some text that shouldn't be red
</div>
color is an inherited property. So if your element has no color set, it inherits the color from the next ancestor element that has a color defined. In your example,
:not(.content) { color: #F00; }
this also targets the body element, so your div.content inherits color: #F00;.
To avoid this, specify inherited properties on the elements you don't want inheritance on.
.content { color: green; }
:not(.content) {
color: red;
}
<div class="content">
Here is some text that shouldn't be red
</div>
Quirks, tricks, and unexpected results of :not
:not(.foo) will match anything that isn't .foo, including <html> and <body>.
You need to increase specificity to avoid this, e.g. div:not(.content).
In addition:
div:not([style^='background']) {
/* also targets parent divs */
color: #00FF00;
}
.content :not([style^='background']) {
/* You have a space here - this targets _children_ of .content
that are :not([style^='background']. Is this what you want? */
color: #00FF00;
}
Remember that the "C" in "CSS" stands for cascading, and one aspect of that is inherited styles. Many styles (such as color) affect children of matched elements too, not just the element itself.

Creating Custom CSS To Override Default CSS

First time here, and was hoping that someone would be able to help with an issue I’ve been dealing with. I’ve had specific details not to modify the original CSS, and instead told to create a new CSS that contains specific overrides for the original CSS. How would I go about doing that efficiently?
Any help would be appreciated. Thanks!
css are applied is a given order. Here are few examples
Case 1: overide default color for a div
div#foo {
color: blue; /* This one is applied to <div id="foo"></div> */
}
div {
color: red;
}
Case 2: css which is loaded at last will be on top.
div {
color: red;
}
div {
color: blue; /* This one is applied to <div id="foo"></div> */
}
case 3: important takes first place
div {
color: red !important;
}
case 4: multiple important
div {
color: red !important;
}
div {
color: yellow !important; /* This will be applied */
}
Include your css file after original css file. Add your custom class in html and use it to override original code.
Don't use !important property it create issue in responsive style.

Apply CSS to any element except for certain class descendants?

Is it possible to apply certain CSS to any element, except descendants of a certain class?
Here's a fiddle: http://jsfiddle.net/68jgdthm
As you can see I want everything on the page to be dark except elements which are descendants of the light class. The trick here is that one can't know if the element is a direct descendant, e.g. it might be this:
<div class="light">
<p>Element</p>
</div>
but it might also be this:
<div class="light">
<div>
<div>
<p>Element</p>
</div>
</div>
</div>
The dark class is almost always added to the body element and will always be a parent of any light classes.
One might say:
Just make the body "light" and add dark classes to any elements you need. - But I actually need the opposite, I need everything to be dark and certain elements to be light.
Then add "light" styles and add the light class to elements you need. - I already have the dark styles, so I'm looking for an easier "excluding" solution (I'm using LESS, so prefixing etc. is quite easy).
You will not be able to exclude descendants this way without writing a separate selector. You won't be able to do this even using :not(), for the reasons stated here.
Fortunately, the fact that .light elements will only ever occur within the context of a .dark element and not vice versa makes this a little easier. Since you have a body CSS rule already, just add .light p to that rule, and move the entire ruleset underneath .dark p so .light p will take precedence:
.dark p {
color: #000;
}
body, .light p {
color: #ccc;
}
Updated fiddle
Alternatively if you want to keep the body rule on top, you could bump up the specificity of .light p to ensure it will take precedence:
body, body .light p {
color: #ccc;
}
.dark p {
color: #000;
}
Color is an inherited property. Therefore just by declaring .dark and .light to have the wanted color is a good thing. You can make a default by assigning it to the body. I think atomic design like this is a good practice, as you don't add too much specificity in your CSS.
You could do this:
body {
color: #ccc;
}
.dark {
color: #000;
}
.light {
color: #fff;
}
Demo: http://jsfiddle.net/68jgdthm/1/

Stop overriding from previous CSS properties

For example, given these two rules
p { color: red; background: yellow }
p { color: green }
paragraphs would appear in green text. They would also have a yellow background however, because the first rule is not completely negated. Its value for the color property is overridden by the second rule but its background-color is not in conflict, so it still applies.
So Is there anyway to stop applying background color property?
I am requiring such method because first rule may have n no. of attributes which i don't know beforehand.
looking forward for positive reply.
That's why you can define classes in CSS.
The style defined for the same element will be always overwritten if there are duplicated properties and inherited from the previous definition for the same element.
Try:
CSS
p.red { color: red; background: yellow }
p.green { color: green }
HTML
<p class="green">Some text</p>
<p class="red">Another text</p>
Define a class to each <p> element. Set CSS style for each defined class.
HTML File (index file)
<p class="content-1">This is content 1</p>
<p class="content-2">This is content 2</p>
CSS file (style.css)
p.content-1 {
color: red; background: yellow;
}
p.content-2 {
color: green;
}
JSFiddle: http://jsfiddle.net/SCLP8/
You can add the background property to your own CSS like this:
p { color: red; background: yellow; }
p { color: green; background: none; }
There won't be a yellow background.