53

Can I use the CSS calc() function when setting positions in JavaScript?

ePopup.style.top = "calc(100px - 1.5em)";
2
  • 9
    I have of course tried this, it didn't seem to work. Did it not work because I have done something syntatically incorrect or because it intrinsically does not work. Commented Nov 29, 2016 at 17:26
  • 3
    @JakeWilson - your edit a few years ago obscured the typo that caused the OP's problem. The post originally showed a ; at the end of the CSS string (within the quotes), which fails leaving the property blank. I made the same blunder and found this. But now it's not clear at all why the OP's code failed. Commented Feb 19, 2021 at 15:31

2 Answers 2

62

Yes, calc() will work when setting styles in javascript.

Working Example:

var innerDiv = document.getElementsByClassName('inner-div')[0];

function growInnerDiv() {
    innerDiv.style.setProperty('width', 'calc(100% + 224px)');
}

innerDiv.addEventListener('click', growInnerDiv, false);
.outer-div {
    display: inline-block;
    width: 200px;
    height: 100px;
    padding: 12px;
    border: 1px solid rgb(255,0,0);
    background-color: rgb(255,255,0);
}

.inner-div {
    width: 100px;
    height: 100px;
    color: rgb(255, 255, 255);
    font-weight: bold;
    text-align: center;
    line-height: 100px;
    font-family: arial, helvetica, sans-serif;
    background-color: rgb(255,0,0);
    cursor: pointer;
    transition: all 0.5s linear;
}
<div class="outer-div">
    <div class="inner-div">Click Me</div>
<div>

Sign up to request clarification or add additional context in comments.

5 Comments

That is good to know that calc can work from Javascript, I will therefore persist with trying to make that work on my page that rather than giving-up and trying alternative methods. Many thanks for that answer despite the question getting seven down marks.
You're most welcome, @NickC. I thought your question entirely fair - when a process is not working, it is vital to isolate the component of that process that isn't working, rather than making assumptions - so I gave your question an upvote.
Yes, @FlorianB, when writing calc() functions in CSS, you must surround the operator with spaces.
Does it mean every CSS function can be used this way?
Yes, @dudung - other CSS functions like min(), max(), clamp() etc. all represent dynamic CSS values which may be applied via JavaScript. For the full list of CSS functions, see: developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions
6

There are some interesting things that happen when you use calc with the same type of units, e.g. 10px + 5px. It gets simplified to 15px by the process that puts it onto the element.

So, to expand on rounin's great answer, here's some examples of that behaviour in action:

function growDiv(e) {
  const thisDiv = e.target;
  const x = 100;
  const y = 42;
  const z = 69;
  let widthVal;

  if (thisDiv.id == "simplifies") {
    widthVal = `calc(${y + z}px + ${x}px + ${y}px)`;
  } else if (thisDiv.id == "mixed-units") {
    widthVal = `calc(0em + ${y + z}px + ${x * 2}px + ${y}px)`;
  } else if (thisDiv.id == "variables") {
    thisDiv.style.setProperty("--x", x + "px");
    thisDiv.style.setProperty("--y", y + "px");
    thisDiv.style.setProperty("--z", z + "px");
    widthVal = "calc((var(--x) * 2) + var(--y) + (var(--z) * 2))";
  }

  thisDiv.style.width = widthVal;
  thisDiv.innerHTML =
    `input: ${widthVal}<br>style:${thisDiv.style.width}`;
}

document
  .querySelectorAll("div")
  .forEach((el) => el.addEventListener("click", growDiv, false));
.inner-div {
  background-color: hotpink;
  color: white;
  font-weight: bold;
  height: 100px;
  margin-bottom: 5px;
  text-align: center;
  transition: all 0.5s linear;
  width: 100px;
}
<div class="inner-div" id="simplifies">simplifies<br />1) Click Me</div>
<div class="inner-div" id="mixed-units">mixed-units<br />2) Click Me</div>
<div class="inner-div" id="variables">variables<br />3) Click Me</div>

  • Div 1 has all the same units, and therefore simplifies.
  • Div 2 has a token 0em unit, which makes no difference to the calculation, but forces the full expression to come through.
  • Div 3 is my favourite because it's a little bit self-documenting. I do this because I'm a bit forgetful and it lets me see why I set that element to 728.3 high, not just that I did.

1 Comment

This explains why something which is simple is better as compared to something which is complicated but the runtime makes it work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.