Defining CSS sub-roots

532 views Asked by At

Suppose I have a --primary-color variable in my :root.

Suppose I have dozens of components that have a color attribute, and I want their color to be the same as the --primary-color. Normally I would have to define their color within the root, e.g.

:root{
  --primary-color: red;
  --calendar-border-color: var(--primary-color);
} 

This is fine for a small amount of simple components, but what if I have dozens and dozens of components, all of which have several attributes that rely on the :root variables? I don't want the root to be hundreds of lines long, and make it hard to navigate to the one component attribute I need to change.

What makes more sense to me, is to have a calendar.css file, and define a subroot/constructor/whatever where I just fetch the root variables, and then can define my own variables for that class, e.g.

calendar.css

:sub-root{
  --calendar-border-color:    var(--primary-color);
  --calendar-highlight-color: var(--secondary-color);
  --calendar-important-color: var(--third-color);
  --calendar-default-color:   var(--default-color);

}

.calendar-border{
  color: var(--calendar-border-color);
  height: 20px;
 //etc...

And from there I can just change that one file where I know where everything is.

I imagine something like this exists, right?

edit:

Seems to work for the most part, but not all the way. Originally, I was calling .calendar in a class name on the main div for the component:

.calendar {
  --calendar-background-color: red;
  background-color: var(--calendar-background-color)
}

So I moved it and renamed the div class name to 'calendar-main':

.calendar{
  --calendar-background-color: red;
}

.calendar-main{
  background-color: var(--calendar-background-color)
}

and this seems to work for some attributes, but not others. any idea what's going on?

1

There are 1 answers

2
Heretic Monkey On BEST ANSWER

From MDN's documentation on Using CSS custom properties:

Declaring a custom property is done using a custom property name that begins with a double hyphen (--), and a property value that can be any valid CSS value. Like any other property, this is written inside a ruleset, like so:

element {
  --main-bg-color: brown;
}

Note that the selector given to the ruleset defines the scope that the custom property can be used in.

Based on that, we can use any selector in place of :root or (in the example quoted) element, and the properties defined in the ruleset will be scoped to that selector.

Without knowing the HTML structure of your component, it's hard to say whether this will work with high confidence, but say your calendar component had a structure like this:

<div class="calendar">
  <select class="month"><option>Select month</option></select>
  <select class="year"><option>Select year</option></select>
  <table>
    <thead>
      <tr>
        <th>S</th>
        <th>M</th>
        <th>T</th>
        <th>W</th>
        <th>T</th>
        <th>F</th>
        <th>S</th>
      </tr>
    </thead>
    <tbody>
     ...days...
    </tbody>
  </table>
</div>

You could then structure your variables like so:

.calendar {
  --calendar-border: #000;
  --calendar-weekday-font-weight: bold;
  --calendar-day-font-weight: normal;
  --calendar-day-today-font-weight: bold;
  --calendar-day-selected-font-weight: bold;
}

.calendar th {
  font-weight: var(--calendar-weekday-font-weight);
}
.calendar td {
  font-weight: var(--calendar-day-font-weight);
}
.calendar td.selected {
  font-weight: var(--calendar-day-selected-font-weight);
}
.calendar td.today {
  font-weight: var(--calendar-day-today-font-weight);
}