Discover the method for accessing a CSS Variable declared within the `:root` selector from within a nested React functional component

Motivation

My main aim is to establish CSS as the primary source for color definitions. I am hesitant to duplicate these values into JavaScript variables as it would require updating code in two separate locations if any changes were made to a specific color.

Within my CSS file, I have a comprehensive list of colors stored as CSS Variables (also known as CSS Property Values).

/* variables.css */
:root {
    --indicator---red: rgba(255, 46, 46, 1);
    --indicator---red--dark: rgba(201, 37, 37, 1);
    --indicator---green: rgba(71, 205, 38, 1);
    --indicator---green--dark: rgba(57, 172, 28, 1);
    --indicator---amber: rgba(244, 182, 60, 1);
    --indicator---amber--dark: rgba(208, 156, 56, 1);
}

Currently, I am using React in my project. I have a functional component called TrafficLight that needs to directly access these colors from my CSS Variables. I intend to accomplish the following:

// TrafficLight.js
function TrafficLight({status}) {
  switch (status) {
    case "GREEN":
     color = getComputedStyle(document.documentElement).getPropertyValue("--indicator-green")
     break;
    case "YELLOW":
     color = getComputedStyle(document.documentElement).getPropertyValue("--indicator-amber")
     break;
    case "RED":
     color = getComputedStyle(document.documentElement).getPropertyValue("--indicator-red");
     break;
  }
  return (<div className="circle" style={{backgroundColor: color}} />);
}

Issue

The challenge I'm encountering is that React is unable to access the CSS Variables defined within :root since

CSSStyleDeclaration.getPropertyValue()
consistently returns an empty string.

Attempted Solutions

  1. Experimenting with using vanilla JavaScript to access the DOM, however, since React operates using a virtual DOM, this method fails to recognize the :root selector:
  • getComputedStyle(document.documentElement).getPropertyValue('--my-var')
  • getComputedStyle(document.body).getPropertyValue('--my-var')
  • window.getComputedStyle(document.documentElement).getPropertyValue('--my-var')
  1. Exploring the option of waiting for the component to mount and conducting the lookups within a useEffect() block.

  2. Trying to avoid utilizing useRef and passing the :root reference down to my component through prop-drilling, given the structure of my project:

<App>
  <Parent1>
    <Parent2>
      <Parent3>
         ... // Several components deep
           <TrafficLight>

Answer №1

To retrieve the CSS Variables without having to verify the computed style, implement a function within the TrafficLight module that determines the color based on the status attribute and directly applies it to the backgroundColor feature.

// TrafficLight.js

function TrafficLight({status}) {
  
  const getColor = () => {
    switch(status) {
      case "GREEN": {
        return "--indicator-green"
      }
      case "GREEN": {
        return "--indicator-amber"
      }
      case "GREEN": {
        return "--indicator-red"
      }
      default: 
        return "--YOUR-DEFAULT-COLOR-IF-THE-OTHERS-DONT-MATCH"
    }
  }

  // leverage the var CSS function to access the attribute
  const myColor = `var(--${getColor()})`; 

  return (<div className="circle" style={{backgroundColor: myColor}} />);
}

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

How can I utilize angular's $http service to fetch a JavaScript file?

I've been exploring the integration of Angular with Node.js and attempting to establish a connection to a MySQL database. Within my script (server.js), I am utilizing the node mysql module as shown below: var mysql=require('mysql'); var ...

Encountering issues with integrating NPM package into Meteor.js

Having installed both the meteor-npm package and the crypto npm package, I encountered some issues while using it in Meteor. npm: updating npm dependencies -- crypto Despite seeing this output in the console, when trying to use the npm package on the ser ...

Navigating Next.js: Mastering the art of localStorage Access

Currently, I am developing my first member area using next.js. My goal is to store some data in localStorage (such as token, expiresAt, userInfo), which will eventually be moved to an http-only cookie. The code below is generating the error: "LocalStorage ...

Issue with retaining entered text in SearchBar results while using React.js

I am encountering some issues with my searchBar.jsx file Currently, when I type a word into the SearchBar, it displays the relevant search results correctly. However, if I delete the entered text, the displayed results revert to their original state. My g ...

worldpay implements the useTemplateForm callback function

My experience with implementing worldpay on my one-page Angular app (Angular 1.x) has been mostly positive. I have been using the useTemplateForm() method to generate a credit card form and retrieve a token successfully. However, I have encountered an issu ...

Retrieve the functions of a React component from an external source

In my code, I have a wrapper class called Class1 that serves as a container for another class called Class2. Within Class1, I have a component called Test. My goal is to pass this Test component into Class2 as a parameter. My question is, is it possible t ...

When using npm link, the connected package fails to update

I am currently working on two modules - my main project and a component library, both utilizing webpack and react. To connect the component library to the main project, I followed these steps: Within the comp-lib directory: Ran npm link Within the pro ...

Invoking a function within a React component using a different React component

Having just started learning ReactJS, I encountered an issue involving two components - comp1 and comp2. Comp1 renders comp2, with comp2 containing a method inside it. When a button in comp1 is clicked, it should call a method inside comp2. However, I am ...

Can HTML be transferred between browser tabs using Angular?

I'm in the process of developing a unique Angular (v17) application that allows users to drag and drop HTML elements, even across multiple browser tabs. I am inspired by the capabilities demonstrated by neo.mjs, as shown in this demo: https://www.yout ...

Is it possible for JavaScript to detect elements or scripts within a hidden element using display="none"?

Is it possible for scripts to locate elements that have been hidden in the DOM by setting their attribute to display="none"? ...

To properly format the date value from the ngModel in Angular before sending it to the payload, I require the date to be in the format

When working with Angular 9, I am facing an issue where I need to format and send my date in a specific way within the payload. Currently, the code is sending the date in this format: otgStartDate: 2021-07-20T09:56:39.000Z, but I actually want it to be for ...

VueJS Unit Testing: Exploring the Content of Attributes- What to Test?

I'm currently facing some challenges with my initial VueJS unit tests using Jest. Although I grasp the concept and have already executed my first set of successful tests, I find myself pondering over the question of "What aspects should I test?" For ...

Stop the slider when a video pops up

Years ago, I had a slider created for me that supports both images and video with a timer. However, the issue I'm facing is that when the timer runs every 10 seconds, the video gets cut off if it's not finished playing. Below is the json file st ...

I am encountering an issue with running my Mocha tests. Can anyone provide assistance on how to solve this problem?

https://i.sstatic.net/kLnxs.png Could the issue be with the package.json file or am I not executing the proper command to run it? ...

Oops! The connection timed out while trying to format the error in SMTPConnection

Encountering an error with a connection timeout while trying to send emails using nodemailer. Seeking assistance as the console keeps showing this error message: Error: Connection timeout at SMTPConnection._formatError (/home/codabae/Desktop/mailmonster/B ...

Arrange array with objects in order of most recent date

I am in the process of developing a chat application where all contacts are stored as objects in one array: var contacts = [{name: "Ruud", age: 20},{name: "Elke", age: 17}]; Next, I have the chat messages for each contact saved in an array of objects: v ...

What is the best way to ensure that the width of dropdown menu items corresponds precisely to the width of the content

I have implemented the Reactstrap drop-down menu: import React from "react"; import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem, } from "reactstrap"; export default class DropDownTest extends React.Component { cons ...

Adding new elements to an array does not activate the reactivity of Vue

After discovering that editing objects within an array doesn't function properly in vue.js due to its limitations, I tried using vue.set to resolve the issue, but it's proving to be quite challenging for me. Let's take a look at the sample ...

What is the reason behind the code breaking when a newline is added between `return` and `(`?

After investigating my query, it seems that a peculiar issue arises in the code where setState fires and render method gets hit, but nothing rerenders The code functions correctly when there is no newline between the return statement and opening parenthes ...

What steps can be taken to enhance the responsiveness of this Bootstrap 4 code?

I've been trying to make this code more responsive, but I haven't found a suitable solution yet. When the browser window shrinks to mobile sizes, the list becomes too narrow and the picture/video items on the right end up small and aesthetically ...