Default values for CSS variables: only apply if the variable has not been previously defined

My Web Component relies on the power of CSS variables.

To set default values for these variables is crucial.

With their wide usage across multiple files, it's essential to define them once and for all.

The initial approach turns the text color to black. But why?

How can I establish the default values correctly just once?

.a {
  --my-variable: red;
}

.b {
  --my-variable: var(--my-variable, blue);
}
<div class="a">
  <div class="b">
    <span style="color: var(--my-variable);">text</span>
  </div>
</div>

Answer №1

Adding to the points made previously, there may arise situations where avoiding declaration of variables in the global :root scope is preferred. This can be especially useful when creating a reusable component that requires its own locally scoped styles, independent of the overarching project styles - particularly if the component is intended for use by other developers.

In such cases, one approach is to expose a single variable name to the wider development environment, while utilizing a different variable name within the component itself. The container for the component simply links the optional external variable to the internal variable and sets its default value:

.my-component-container {
  /* Link optional "external" variables to required "internal" variables */
  --my-variable-inner: var(--my-variable, blue);
}

.my-component-container .my-nested-element {
  color: var(--my-variable-inner);
}

.my-component-container .my-other-nested-element {
  border-color: var(--my-variable-inner);
}

This method ensures that --my-variable-inner is consistently defined within the component, while allowing external users the flexibility to define --my-variable as needed.

The trade-off here is managing two variable names instead of one. To streamline this process, consider implementing a project-wide convention, such as appending --inner or another uniform suffix to each relevant variable.

Answer №2

Use the :root selector to set default values, then override them in specific selectors.

:root {
  --primary-color: red;
}

* {
  color: var(--primary-color);
  border: 1px solid var(--primary-color);
  padding: 0.25rem;
  margin: 0;
}

div {
  --primary-color: green;
}

p {
  --primary-color: blue;
}
<div>HI!</div>
&hellip;
<p>Bye!</p>

Answer №3

Why does the initial attempt result in black text?

The reason for this is that the code

--my-variable: var(--my-variable, blue);
is invalid since it tries to define a variable with itself, which is not allowed. As a result, the browser will ignore this declaration. Subsequently, when trying to use color: var(--my-variable);, the color falls back to the initial value, which is black.

To resolve this issue, it is recommended to define the variable at a higher level where it can be inherited by all elements (as suggested by @kornieff).


As stated in the specification:

Custom properties are mostly left unevaluated, except for allowing and evaluating the var() function within their values. This may lead to cyclic dependencies when a custom property references itself using var(), or when multiple custom properties refer to each other.

For each element, a directed dependency graph is created, featuring nodes representing each custom property. If a custom property prop's value includes a var() function referring to the property var (including in the fallback argument of var()), an edge is added between prop and var. It is possible for edges to point from a custom property to itself. If there is a cycle in the dependency graph, all custom properties involved in the cycle must revert to their initial value (which is essentially an invalid value).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on customizing a dropdown button in a class-based Angular library with version 4 or higher

My dilemma revolves around utilizing the Angular Material library for a drop-down navigation bar. The issue at hand is my desire to hover through the list, yet I am unable to tweak the style within HTML. Fortunately, I can easily make alterations in Chrome ...

Navigating through directories in an HTML file

In my directory, the folders are named in uppercase letters and have the following structure: ONLINESHOP |-- index.html |-- COMPONENTS |-- CONFIG |-- TEMPLATES |-- CSS |-- main-style.css |-- CONTROLLERS |-- MODE ...

Updating the default color of selected text within a webpage's content

Is there a way to modify the default blue color that appears when content is selected on a webpage? I am wondering how to change this selection color to a custom color of choice. ...

Showcase text in a straight row by utilizing ng-repeat and bootstrap

My goal is to show each word on a new line, similar to how words are displayed in a hangman game. The words should be displayed as blanks. <body ng-init="models = [['H','a','p','p','y'],['X',& ...

How can I center my dynamic CSS3 menu with varying widths?

I am facing an issue with my css menu where the width is set to 400 for non-Admin users and 500 for Admins. The problem arises when I center the menu for Admins by setting the UL width to 500, as it appears off-kilter for non-admin users whose menu is only ...

Animation in CSS3: Blinking overlay block

I am interested in creating an element that will overlay a section of a webpage using position: absolute. The element should be 50% opaque and blink between red and transparent, similar to the way OSX used to do with default dialog buttons. Is there a way ...

In a carousel slider, the height and width of divs are not set to specific dimensions

For a code snippet, you can visit this link: here The html: <html lang="en"> <head> <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700,700i|Merriweather:300,400,700" rel="stylesheet"> <link href="https://ma ...

Several problems with CSS regarding DIV height set to 100% and the content inside

I'm facing a bit of a puzzle here. I have a div that spans the full height of the browser, with a background set to 100% size and image content contained in two inline divs that are vertically aligned in the middle. In one of these divs, the image is ...

Conflicting Transformation Properties Causing CSS Issues Within a Single Element

I'm currently working on a user interface where users can drag and drop a box with a red outline to position it on the screen within a black box. See the UI here Alternatively, users can also move the box by adjusting the inputs on the right side. ...

Implementing jQuery form validation including checking for the strength of the password

My understanding of jQuery was quite basic until I began working on jQuery form validation with password strength check. I successfully completed the password strength check portion, but now I am unsure of how to enable the submit button once the condition ...

Another class is overriding the border of the text-box

I'm facing a challenge in customizing the material ui css. Specifically, I want to set the border color of a textbox to red. The issue arises when the bottom border gets overwritten. Upon investigation, I discovered that the culprit is the class MuiIn ...

Search field in DataTables appears to be misaligned

I'm in the process of developing a small website using JSP and DataTables (currently only for the first table). Here's what I have so far: As you can observe, there seems to be an alignment issue with the search field position. I'm n ...

Show a triangle positioned on the left side of the display

Looking for help with aligning a div to the left side of the screen CSS #nav { position: fixed; height: 50px; width: 50px; display: block; background-color: #000; } This particular div contains an icon that acts as a link HTML <div id="nav"> ...

CSS - When using both display: flex and position: absolute, the anchor point is shifted

I have a flexbox element with three children. I want the second child to overlap the first child using absolute positioning, like this: Desired Outcome: https://i.stack.imgur.com/i479w.png It's important that the second child appears on top of the ...

Update the div element without needing to reload the entire page

Is there a way to reload a div tag without refreshing the entire page? I understand this question has been asked before, but I want to make sure I have a clear understanding. <p>click HERE</p> <div class="sample"> <?php functi ...

Tips for distinguishing the beginning and ending points of wrapped text in the Firefox browser

Within my work, I am utilizing a contentEditable span where I aim to position an element with position: absolute on the same line as the cursor. However, issues arise when text wrapping occurs - causing abnormal behavior at the start and end of wrapped lin ...

Using JQuery to switch out images that do not have an ID or class assigned

Currently, I am using a Google Chrome Extension to apply an external theme to a website. Unfortunately, the logo on the site does not have an ID or class that can be used to call it. I am searching for a solution to replace it with a different image. My ...

The process involves transferring information from a specific div element to a database. This particular div element obtains its data after receiving an appended ID

It's a bit complicated, but I'm working on creating a tag system. I'm fetching data from a database with an AJAX call using the "@" symbol. Everything is working fine - the tags are being generated, but I'm having trouble retrieving and ...

Tips for creating a Bootstrap table with a "table-bordered" style, fixed header, and scrollable body

How can I keep the table header fixed while allowing the body to scroll without breaking the table layout? I've tried using the CSS below, but it results in the width of the header columns being different from the width of the body columns. Any sugges ...

What is the best method for getting rid of blank white space on my website?

Having some trouble removing unnecessary white space on my website. The goal is to have the main text and logo centered on an image background, but I've been unsuccessful so far. I've experimented with different CSS properties like overflow-x: ...