Search code examples
csscss-variablescss-calc

Unable to overwrite CSS variable with its own value


Lets assume to have the following CSS:

.box {
  width: var(--box-size);
  height: var(--box-size);
  border: 1px solid red;
}

.box--larger {
  --box-size: 66px;
}

.box--larger1 {
  --box-size: calc(var(--box-size) + var(--box--larger));
}

.box--larger2 {
  --box-size: calc(50px + var(--box--larger));
}

:root {
  --box-size: 50px; 
  --box--larger: 16px;
}
<div class="box">1</div>
<div class="box box--larger">2</div>
<div class="box box--larger1">3</div>
<div class="box box--larger2">4</div>

I wonder why boxes 1 and 2 work but box 3 doesn't. I would expect box 3 to look the same as box 2 but it doesn't. I tested box 3's approach in Chrome and I found that var(--box-size) doesn't show a value but var(--box-larger) does return the right value (16px).

Could someone explain why the approach of box 3 doesn't work. I mean to me it looks like valid CSS.


Solution

  • As commented above, CSS is not C++ and you are having a cyclic dependency wanting to express a property with the same property which will not work.

    Refering to 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.

    A common fix to that situation is to add more variables to avoid any cyclic dependency.

    :root {
      --bs:50px;
      --bl:16px;
      --box-size:var(--bs); 
      --box--larger:var(--bl);
    }
    
    .box {
      width: var(--box-size);
      height: var(--box-size);
      border: 1px solid red;
    }
    
    .box--larger {
      --box-size: 66px;
    }
    
    .box--larger1 {
      --box-size: calc(var(--bs) + var(--bl));
    }
    
    .box--larger2 {
      --box-size: calc(50px + var(--bl));
    }
    <div class="box">1</div>
    <div class="box box--larger">2</div>
    <div class="box box--larger1">3</div>
    <div class="box box--larger2">4</div>