Get computed value of CSS variable that uses an expression like calc
Technically you cannot because the computed value is not static and will depend on other properties. In this case it's trivial since we are dealing with pixel value but imagine the case where you will have percentage value. Percentage is relative to other properties so we cannot compute it until it's used with var()
. Same logic if we use unit like em
, ch
, etc
Here is a simple example to illustrate:
let div = document.getElementById('example');console.log(window.getComputedStyle(div).getPropertyValue('--example-var'))console.log(window.getComputedStyle(div).getPropertyValue('font-size'))console.log(window.getComputedStyle(div).getPropertyValue('width'))console.log(window.getComputedStyle(div).getPropertyValue('background-size'));
:root { --example-var: calc(100% + 5px - 10px);}#example { font-size:var(--example-var); width:var(--example-var); background-size:var(--example-var);}
<div id='example'>some text</div>
Getting CSS Variables to Add Correctly using calc()
because when doing #century-*:checked~ #century_result
you only assign the value to #century_result
so #result
will get nothing. You need to target both element so simply do #century-*:checked ~ *
(same logic with #month_result
)
:root {
--isLeapYear: 0;
/* Determinant to be worked out later, set as 0 for now */
/* Month registers */
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 0;
--m0: 0;
/* Century keys */
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 1;
--ck0: 0;
--century: 0;
--month: 0;
--result: 0;
--borderBlack: 1px solid black;
--selectedColor: #007ec2;
}
[type="radio"],
[type="checkbox"] {
display: none;
}
.century+label,
.month+label {
padding-left: 4px;
padding-right: 4px;
height: 16px;
border-left: var(--borderBlack);
border-right: var(--borderBlack);
font: 400 13.3333px Arial;
display: inline-block;
background-color: white;
color: black;
}
.century+label {
width: 20px;
left: 5px;
top: 5px;
}
.month+label {
width: 80px;
position: relative;
left: 73px;
top: -224px;
}
label[for="month-01"],
label[for="century-18"] {
border-top: var(--borderBlack);
}
label[for="month-12"],
label[for="century-29"] {
border-bottom: var(--borderBlack);
}
input:checked+label {
background-color: var(--selectedColor);
color: white;
}
/* Century Keys */
#century-18:checked~ * {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 0;
--ck1: 1;
--ck0: 0;
/* 2 */
}
#century-19:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 0;
--ck1: 0;
--ck0: 0;
/* 0 */
}
#century-20:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 1;
--ck0: 0;
/* 6*/
}
#century-21:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 0;
--ck0: 0;
/* 4 */
}
#century-22:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 0;
--ck1: 1;
--ck0: 0;
/* 2 */
}
#century-23:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 0;
--ck1: 0;
--ck0: 0;
/* 0 */
}
#century-24:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 1;
--ck0: 0;
/* 6 */
}
#century-25:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 0;
--ck0: 0;
/* 4 */
}
#century-26:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 0;
--ck1: 1;
--ck0: 0;
/* 2 */
}
#century-27:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 0;
--ck1: 0;
--ck0: 0;
/* 0 */
}
#century-28:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 1;
--ck0: 0;
/* 6 */
}
#century-29:checked~* {
--ck7: 0;
--ck6: 0;
--ck5: 0;
--ck4: 0;
--ck3: 0;
--ck2: 1;
--ck1: 0;
--ck0: 0;
/* 4 */
}
/* Month Keys */
.month[value="1"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 0;
--m0: calc(1 - var(--isLeapYear));
}
.month[value="2"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: calc(1 - var(--isLeapYear));
--m1: var(--isLeapYear);
--m0: var(--isLeapYear);
}
.month[value="3"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 1;
--m1: 0;
--m0: 0;
}
.month[value="4"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 0;
--m0: 0;
}
.month[value="5"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 1;
--m0: 0;
}
.month[value="6"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 1;
--m1: 0;
--m0: 1;
}
.month[value="7"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 0;
--m0: 0;
}
.month[value="8"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 1;
--m0: 1;
}
.month[value="9"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 1;
--m1: 1;
--m0: 0;
}
.month[value="10"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 0;
--m1: 0;
--m0: 1;
}
.month[value="11"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 1;
--m1: 0;
--m0: 0;
}
.month[value="12"]:checked~* {
--m7: 0;
--m6: 0;
--m5: 0;
--m4: 0;
--m3: 0;
--m2: 1;
--m1: 1;
--m0: 0;
}
.century:checked~* {
font-family: Courier;
font-weight: 700;
--century: calc(var(--ck7) * 128 + var(--ck6) * 64 + var(--ck5) * 32 + var(--ck4) * 16 + var(--ck3) * 8 + var(--ck2) * 4 + var(--ck1) * 2 + var(--ck0));
}
#century_result:after {
counter-reset: C7 var(--ck7) C6 var(--ck6) C5 var(--ck5) C4 var(--ck4) C3 var(--ck3) C2 var(--ck2) C1 var(--ck1) C0 var(--ck0) CENTURY 0;
counter-increment: CENTURY var(--century);
content: "C" counter(C7) counter(C6) counter(C5) counter(C4) counter(C3) counter(C2) counter(C1) counter(C0) " = " counter(CENTURY)
}
.month:checked~#month_result {
font-family: Courier;
font-weight: 700;
--month: calc(var(--m7) * 128 + var(--m6) * 64 + var(--m5) * 32 + var(--m4) * 16 + var(--m3) * 8 + var(--m2) * 4 + var(--m1) * 2 + var(--m0));
}
#month_result:after {
counter-reset: M7 var(--m7) M6 var(--m6) M5 var(--m5) M4 var(--m4) M3 var(--m3) M2 var(--m2) M1 var(--m1) M0 var(--m0) MONTH 0;
counter-increment: MONTH var(--month);
content: "M" counter(M7) counter(M6) counter(M5) counter(M4) counter(M3) counter(M2) counter(M1) counter(M0) " = " counter(MONTH)
}
#result {
font-family: Courier;
font-weight: 700;
--century: calc(var(--ck7) * 128 + var(--ck6) * 64 + var(--ck5) * 32 + var(--ck4) * 16 + var(--ck3) * 8 + var(--ck2) * 4 + var(--ck1) * 2 + var(--ck0));
--month: calc(var(--m7) * 128 + var(--m6) * 64 + var(--m5) * 32 + var(--m4) * 16 + var(--m3) * 8 + var(--m2) * 4 + var(--m1) * 2 + var(--m0));
--result: calc(var(--century) + var(--month));
}
#result:after {
counter-reset: RESULT 0;
counter-increment: RESULT var(--result);
content: "R = " counter(RESULT);
}
#century_result {
position: absolute;
top: 240px;
}
#month_result {
position: absolute;
top: 265px;
}
#result {
position: absolute;
top: 290px;
}
<input id="century-18" name="century" class="century" type="radio" value="18" /><label for="century-18">18</label><br />
<input id="century-19" name="century" class="century" type="radio" value="19" /><label for="century-19">19</label><br />
<input id="century-20" name="century" class="century" type="radio" value="20" checked="checked" /><label for="century-20">20</label><br />
<input id="century-21" name="century" class="century" type="radio" value="21" /><label for="century-21">21</label><br />
<input id="century-22" name="century" class="century" type="radio" value="22" /><label for="century-22">22</label><br />
<input id="century-23" name="century" class="century" type="radio" value="23" /><label for="century-23">23</label><br />
<input id="century-24" name="century" class="century" type="radio" value="24" /><label for="century-24">24</label><br />
<input id="century-25" name="century" class="century" type="radio" value="25" /><label for="century-25">25</label><br />
<input id="century-26" name="century" class="century" type="radio" value="26" /><label for="century-26">26</label><br />
<input id="century-27" name="century" class="century" type="radio" value="27" /><label for="century-27">27</label><br />
<input id="century-28" name="century" class="century" type="radio" value="28" /><label for="century-28">28</label><br />
<input id="century-29" name="century" class="century" type="radio" value="29" /><label for="century-29">29</label><br />
<input id="month-01" name="month" class="month" type="radio" value="1" checked="checked" /><label for="month-01">January</label><br />
<input id="month-02" name="month" class="month" type="radio" value="2" /><label for="month-02">February</label><br />
<input id="month-03" name="month" class="month" type="radio" value="3" /><label for="month-03">March</label><br />
<input id="month-04" name="month" class="month" type="radio" value="4" /><label for="month-04">April</label><br />
<input id="month-05" name="month" class="month" type="radio" value="5" /><label for="month-05">May</label><br />
<input id="month-06" name="month" class="month" type="radio" value="6" /><label for="month-06">June</label><br />
<input id="month-07" name="month" class="month" type="radio" value="7" /><label for="month-07">July</label><br />
<input id="month-08" name="month" class="month" type="radio" value="8" /><label for="month-08">August</label><br />
<input id="month-09" name="month" class="month" type="radio" value="9" /><label for="month-09">September</label><br />
<input id="month-10" name="month" class="month" type="radio" value="10" /><label for="month-10">October</label><br />
<input id="month-11" name="month" class="month" type="radio" value="11" /><label for="month-11">November</label><br />
<input id="month-12" name="month" class="month" type="radio" value="12" /><label for="month-12">December</label><br />
<div id="century_result"></div>
<div id="month_result"></div>
<div id="result"></div>
Getting a calc() CSS variable into JavaScript
- Problem was, you are access root values which returns string.
- and
calc()
function cannot calculate multiplication of 100ms * 44 so, I have changed--loaderSpeed:100
removedms
. and also created new valiable calledloaderSecondsMultiplier
. - After that, I have
getPropertyValue
get css variables values and converted them into a number and then just mutiply them and in last store it infinalTimeout
.
//GETTING DOCUMENT STYLES
let docStyle = getComputedStyle(document.documentElement);
// GEETING CSS VARIABLE VALUES
let loaderSpeed = parseInt(docStyle.getPropertyValue('--loaderSpeed'));
let loaderSecondsMultiplier = parseInt(docStyle.getPropertyValue('--loaderSecondsMultiplier'));
// MUTIPLYING AND STORING IT'S VALUE TO finalTimeout
let finalTimeout = loaderSpeed * loaderSecondsMultiplier;
setTimeout(() => {
const box = document.getElementById('loaderWrapper');
box.style.display = 'none';
}, finalTimeout);
:root {
--loaderSpeed: 100;
--loaderSecondsMultiplier: 44;
}
<div id="loaderWrapper">
<h1>hey</h1>
</div>
css vars which use calc don't update
Yes, this is expected behavior and in fact completely respectful of the cascading nature of custom properties. From section 2.2 of the spec:
It is important to note that custom properties resolve any var() functions in their values at computed-value time, which occurs before the value is inherited.
This means that the value of the custom property --font-size
as it appears on the root element is really calc(1 * 16px)
, not calc(var(--font-size-mult) * 16px)
, because the var(--font-size-mult)
expression is evaluated when --font-size
is computed for the root element.
This computed value, calc(1 * 16px)
, is then inherited by descendants. Any new value you set for --font-size-mult
on any descendants is ignored (unless other references to it exist).
Should this be the expected behavior? Well, I can only tell you that the spec claims this is required to prevent cyclic references between ancestors and descendants. In the same paragraph as the sentence quoted above:
In general, cyclic dependencies occur only when multiple custom properties on the same element refer to each other; custom properties defined on elements higher in the element tree can never cause a cyclic reference with properties defined on elements lower in the element tree.
Finally, while Kriszta's answer demonstrates the right way to use calc()
with custom properties taking inheritance into account, you should be using the rem unit instead of custom properties entirely, as that unit was made specifically for this use case.
Sass Variable in CSS calc() function
Interpolate:
body
height: calc(100% - #{$body_padding})
For this case, border-box would also suffice:
body
box-sizing: border-box
height: 100%
padding-top: $body_padding
How can I get a negative value of a CSS variables in a calc() expression?
Yes you can do it. Simply multiply by -1
:
:root { --margin: 50px;}
body { margin: 0 100px; border:1px solid;}
.box-1 { background: red; height: 100px; width: 200px; margin-left: calc(-1 * var(--margin));}
.box-2 { background: green; height: 100px; width: 200px; margin-left: calc(-1 * (-1 * var(--margin))); /* You can also nest calculation */}
<div class="box-1"></div><div class="box-2"></div>
Related Topics
Sticky Header Flickering on Safari Desktop Only When Anchor Scrolling
How to Force Jquery to Center an Element When It Is Dragged to and Snapped to Another Container
How to Read/Parse Individual Transform Style Values in JavaScript
How to Make the Browser See CSS and JavaScript Changes
How to Reverse the Order of Nested Child Elements
Need Help to Replace Stoppropagation() JavaScript
How to Style a Unicode Character
How to Get Display:Table-Cell Support in Ie? Any Pure JavaScript or Jquery Workaround
Make the on Scroll Growing <Path> to Dashed Line
Capture/Save/Export an Image with CSS Filter Effects Applied
How to Get the Opacity of an Element Using JavaScript
Using Media Queries to Only Include Js Files on Mobile
How to Dynamically Change CSS Style Attribute of Div Tag
How to Properly Escape Attribute Values in CSS/Js Attribute Selector [Attr=Value]
Customize Ng-Repeat in Angularjs for Every Nth Element
Rotating a Div How to Set Around Which Point to Rotate
Typical Pitfalls of Cross-Browser Compatibility
How to Change Url in Browser Without Navigating Away from Page