Search code examples
htmlcsscss-variables

use data-attr to dynamically pick css custom property


Given the following snippet:

:root{
  --warning: rgb(230, 126, 34);
  --warning-bg: rgba(230, 126, 34, 0.1);

  --important: rgb(52, 152, 219);
  --important-bg: rgba(52, 152, 219, 0.1);

  --caution: rgb(231, 76, 60);
  --caution-bg: rgba(231, 76, 60, 0.1);
}

[data-type]{
  padding: 12px;
  margin: 12px;
}

[data-type="warning"]{
  background-color: var(--warning-bg);
  border: 1px solid var(--warning);
}

[data-type="important"]{
  background-color: var(--important-bg);
  border: 1px solid var(--important);
}

[data-type="caution"]{
  background-color: var(--caution-bg);
  border: 1px solid var(--caution);
}
<div class='block' data-type='warning'>
  <span>Block: Warning</span>
</div>

<div class='block' data-type='important'>
  <span>Block: Important</span>
</div>

<div class='block' data-type='caution'>
  <span>Block: Caution</span>
</div>

Can I use the data-type attribute to pick a custom property (var) from CSS, so that I don't have to repeatedly add the styles for each data-type?

The data-type property comes from an external source and the colors are always in sync with all the data-type(s)

Something along the lines of:

[data-type]{
  background-color: var(--#{attr(data-type)}-bg);
  padding: 12px;
  border: 1px solid var(--#{attr(data-type)});
  margin: 12px;
}

NOTE: Using SASS/LESS is a no-go due to factors beyond my control.


Solution

  • If you are not averse to using a small piece of Javascript to perform the necessary assignments then perhaps this might be of interest.

    This uses getComputedStyle and getPropertyValue to retrieve the variables and setProperty to assign the dynamically created style to the elements.

    let root=document.documentElement;
    let col=document.querySelectorAll('div[data-type]');
        col.forEach( n=>{
          n.style.setProperty('background-color',getComputedStyle(root).getPropertyValue('--'+n.dataset.type+'-bg') );
          n.style.setProperty('border',['1px solid',getComputedStyle(root).getPropertyValue('--'+n.dataset.type)].join(' '));
        });
    :root{
      --warning: rgb(230, 126, 34);
      --warning-bg: rgba(230, 126, 34, 0.1);
    
      --important: rgb(52, 152, 219);
      --important-bg: rgba(52, 152, 219, 0.1);
    
      --caution: rgb(231, 76, 60);
      --caution-bg: rgba(231, 76, 60, 0.1);
    }
    
    [data-type]{
      padding: 12px;
      margin: 12px;
    }
    <div class='block' data-type='warning'>
      <span>Block: Warning</span>
    </div>
    
    <div class='block' data-type='important'>
      <span>Block: Important</span>
    </div>
    
    <div class='block' data-type='caution'>
      <span>Block: Caution</span>
    </div>