CSS Variables Defaults: Set If Not Already Set

CSS variables defaults: set if not already set

This first attempt makes the text black. Why?

Because this --my-variable: var(--my-variable, blue); is invalid as you are trying to express the same variable with itself which is not allowed so the browser will simply ignore it. Then later when using color: var(--my-variable); the color will fallback to the initial value which is black.

The correct way is to simply define the variable on an upper level and it will get inherited by all the element (like the solution provided by @kornieff)


From the specification:

Custom properties are left almost entirely unevaluated, except that they allow and evaluate the var() function in their value. This can create cyclic dependencies where a custom property uses a var() referring to itself, or two or more custom properties each attempt to refer to each other.

For each element, create a directed dependency graph, containing nodes for each custom property. If the value of a custom property prop contains a var() function referring to the property var (including in the fallback argument of var()), add an edge between prop and the var. Edges are possible from a custom property to itself. If there is a cycle in the dependency graph, all the custom properties in the cycle must compute to their initial value (which is a guaranteed-invalid value).

Inherit a CSS variable, or fallback to default

You can't override a variable with itself, so what I can suggest is to define a second variable that will contain your fallback value for each context:

:root {
--fallback-bg: green;
}
.some-component {
display: contents;
--fallback-bg: red;
}
.some-component__container {
background-color: var(--background-color, var(--fallback-bg));
height: 100px;
width: 100px;
}

You can also define a fallback for your fallback if you'd like:
background-color: var(--background-color, var(--fallback-bg, green));

css variable - default value on var not getting passed

Custom properties inherit.

From the spec:

Custom properties are ordinary properties, so they can be declared on
any element, are resolved with the normal inheritance and cascade
rules, ...

This means that if no value is set for a custom property on a given element, the value of its parent is used.

In this case, the parent element defines the custom property: --span:

<div class="item" style="--span: 7">

So the value of the --span property will be 7 on all the children - unless a different value is explicitly defined on a child.

Now the difference between the two versions of the code is clear.

In the commented version, var(--span, 1) in the .item class evaluates to 7 due to inheritance

Since there are only 2 columns in the grid, each item spans the full grid width

In the uncommented version (with --span: 1; defined in the .item class), var(--span, 1) in the .item class evaluates to 1 - because it is explicitly defined on the child.

NB

Fallback values are only used as the substitution value when a given custom property is invalid / not defined

In this case, the second item in the outer grid defines the --span custom property with value 7 and it is available to all its child elements.

css variables - declare variable if not already defined

CSS stands for cascading style sheets,
so you cannot override anything by a parent...

The only way is to create a stronger rule.

look at .c1 and .p1

.parent {  --background: red;}
.child { --size: 30px; --background: green; /* this wins */
background-color: var(--background); width: var(--size); height: var(--size);}
.p1 .c1 { --background: red; /* this wins */}
.c1 { --size: 30px; --background: green;
background-color: var(--background); width: var(--size); height: var(--size);}
<div class="parent">  <div class="child"></div>  </div>
<hr />
<div class="p1"> <div class="c1"></div> </div>

Is it possible to check if a CSS variable is defined or not?

Because what I would like is that when the variable is not define to get the style that it will have if that line was not there in the CSS.

This is not possible even if you use an invalid value.

From the specification

A declaration can be invalid at computed-value time if it contains a var() that references a custom property with its initial value, as explained above, or if it uses a valid custom property, but the property value, after substituting its var() functions, is invalid. When this happens, the computed value of the property is either the property’s inherited value or its initial value depending on whether the property is inherited or not

And

If a property contains one or more var() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after var() functions have been substituted.

So any property using a css variable will be valid whatever its content. It will be invalid only at computed time and will fallback to inherit or initial (never to another value specified somewhere else)

See the below example.

html {
background:red;
background:lol-gradient(var(--c), super-power-red-color);
}

how to reset a CSS variable (aka custom properties) and use the fallback one?

You can unset the value using initial to use the fallback one:

:root {  --border-width-top: 2px;  --border-width-right: 2px;  --border-width-bottom: 2px;  --border-width-left: 2px;  --border-width: 0;}div {  margin:5px;  border-color: red;  border-style: solid;  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));}

div.box { --border-width:initial; --border-width-top: 10px;}
<div>some content</div><div class="box">some content</div>

How to use CSS Variables only when they exist?

You can specify the fallback property like var(--tintColor, blue) - see demo below: