31

Is it possible to do a square-root function in the calc() function of my CSS file? I've read that calc() only supports the basic operators like + - * and /.

Ideally, it'd look something like this:

width: calc(50% - (sqrt(7200))px);

If calc() do not have a sqrt function, what can I do?

tbodt
  • 16,609
  • 6
  • 58
  • 83
dayuloli
  • 16,205
  • 16
  • 71
  • 126
  • 3
    I don't think a sqrt operation is possible. But sqrt(7200) is just a number. Why dont you calculate it by hand? – s_qw23 Apr 27 '13 at 11:20
  • 2
    Why do you need to find a square root in CSS? – David Thomas Apr 27 '13 at 11:21
  • 1
    If you are using sqrt, you will obviously use variables right? Because if it was a constant, it can be calculated by hand. – Achshar Apr 27 '13 at 11:22
  • 1
    I cannot think of a single reason to need square roots in the design of a webpage. – sevenseacat Apr 27 '13 at 11:25
  • @sevenseacat maybe animation calculations? – Achshar Apr 27 '13 at 11:26
  • Animation is behaviour, not presentation. Doesn't belong in CSS. – sevenseacat Apr 27 '13 at 11:27
  • 9
    @sevenseacat: But animations are for show, right? How is that not presentation? – BoltClock Apr 27 '13 at 11:28
  • 1
    @sevenseacat https://developer.mozilla.org/en-US/docs/CSS/Tutorials/Using_CSS_animations – Achshar Apr 27 '13 at 11:28
  • 1
    Animation is not presentation? Ok... – Miljan Puzović Apr 27 '13 at 11:28
  • 1
    OK, basically, I have a rectangular
    , I am trying to position that rectangle accurately relative to a circle - I am trying to make the corner of the rectangle touch the circumference of the circle, at a specific point. Through doing some trig, I determined I need to find the square root of a number, which I didn't want to simply type in integers because 1) it's not accurate 2) it doesn't look good 3) it's not elegant
    – dayuloli Apr 27 '13 at 11:32
  • The advantage of a preprocessing system is that if you make the radius a variable to fit changes in screen sizes, you can have the preprocessor change the CSS positioning. However, perhaps there is something else you can do with ``. – Eric Jablow Apr 27 '13 at 22:51
  • in IE9 this caused the browser to stop working *background-position-x: calc(100% - 2px);* – Rumplin Apr 03 '14 at 10:18
  • 2
    @sevenseacat Anything involving calculating triangles would need sqrt, and that is pure presentation, nothing to do with animations. – Rohan Nicholls Sep 22 '15 at 09:07
  • 2
    Here's my square-root-needing purpose: I want a linear gradient that will obscure the top-left and bottom-right parts of a `div` to make a perfect parallelogram at a certain angle. Also, the `div`'s width is `100vw` and its height is `calc(100vh - 60px)`, so the square root needs to happen in the `calc()` and not in a preprocessor. – 75th Trombone Oct 06 '16 at 19:05

4 Answers4

27

As others suggested, if dealing with repeat values, just use a preprocessor, or copy/paste if from the calculator directly, e.g. sqrt(2) = 1.4142135623730950488016887242097.

But if you really have to use a dynamic way to calculate the square root in CSS dynamically and without JS, there is of course. While a precision of 5 seems enough for most cases, for the number 7200 in your example we should bump it up to a precision of 9+, unless you could make an initial guess, which is closer to the result, but that’s out of question for now.

But without optimization this will bloat your document by 50.000+ extra characters, if using the generated output from the other answer/suggestion.

Since we use it dynamically, we ought to use CSS variables, which limits the browser compatibility a bit, but it already has a global support of about 88% by now (Mar/2018).

Here we go:

#test {
    --number: 7200;
    --guess01: calc((var(--number) + ( var(--number) / var(--number))) / 2);
    --guess02: calc((var(--guess01) + ( var(--number) / var(--guess01))) / 2);
    --guess03: calc((var(--guess02) + ( var(--number) / var(--guess02))) / 2);
    --guess04: calc((var(--guess03) + ( var(--number) / var(--guess03))) / 2);
    --guess05: calc((var(--guess04) + ( var(--number) / var(--guess04))) / 2);
    --guess06: calc((var(--guess05) + ( var(--number) / var(--guess05))) / 2);
    --guess07: calc((var(--guess06) + ( var(--number) / var(--guess06))) / 2);
    --guess08: calc((var(--guess07) + ( var(--number) / var(--guess07))) / 2);
    --guess09: calc((var(--guess08) + ( var(--number) / var(--guess08))) / 2);
    --guess10: calc((var(--guess09) + ( var(--number) / var(--guess09))) / 2);

    width:calc(50% - (var(--guess10) * 1px));
    height:200px;
    background: black;
    padding:20px;
    color:#fff;
}
<div id="test">Width is 50% - sqrt(7200) in px</div>
mountarreat
  • 339
  • 1
  • 4
  • 3
  • 2
    This is a really good answer which actually let's you use square roots calculations with CSS variables which would be useful for dynamic calculations, most noticeably spacing and fonts across responsive designs. Nicely done. Would love to see the same for exponents. – limitlessloop Oct 16 '19 at 22:10
13

You can use a preprocessing system for CSS. For example, you can use Compass and Sass. Compass has a sqrt function.

Why? Perhaps for print styling, or maybe to experiment with the golden mean.

Eric Jablow
  • 7,874
  • 2
  • 22
  • 29
9

According to spec here http://www.w3.org/TR/css3-values/#calc

The calc() function allows mathematical expressions with addition (‘+’), subtraction (‘-’), multiplication (‘*’), and division (‘/’) to be used as component values. The ‘calc()’ expression represents the result of the mathematical calculation it contains, using standard operator precedence rules. It can be used wherever <length>, <frequency>, <angle>, <time>, <number>, or <integer> values are allowed. Components of a ‘calc()’ expression can be literal values, ‘attr()’ or ‘calc()’ expressions, or values that resolve to one of the preceding types.

So you can't calc square roots directly in css for now.. unfortunately :(

Nedudi
  • 5,639
  • 2
  • 42
  • 37
5

I believe that you are interested in dynamically calculating the square root of a number. Contrary to popular belief, you should be able to approximate the square root of a number using only calc. Unfortunately, should is a world of a difference between reality. In reality, or chrome at least, the greatest thing in css, calc, is annoyingly limited in being incapable of doing multiplication or division with 2 variable multiplicands. In said perfect world, the following would work. Click Run Code Snippet.

var nth=document.getElementById('nth'),
    percision=document.getElementById('percision'),
    counter=document.getElementById('counter'),
    input=document.getElementById('input'),
    output=document.getElementById('output');

percision.oninput = function(){
    counter.innerText = percision.value;
};
//var base = "(X+A/X)/2";
var base = 'calc(calc(X + calc(A / X)) / 2)';
(nth.onchange = percision.onchange =
input.onchange = function(){
    nth.value = parseInt(nth.value);
    counter.innerText = percision.value;
    var cur=base, i=percision.value;
    while (i--){
        cur = cur.replace(/X/g, base);
    }
    cur = cur.replace(/A/g, input.value)
             .replace(/X/g, '1');
    output.value = cur;
})();
body, body *:not(script) {
  white-space: nowrap;
  margin-top: 4px;
  margin-top: 4px;
  font-family: monospace;
}
h1 {
  text-align: center;
  margin-bottom: 10px;
}
#nth {
  width: 64px;
  text-align: center;
}
nthText {
  visibility: hidden; /* not yet implemented */
  display: none;
}
#percision {
 width: 192px;
}
#input {
 width: calc(100% - 154px);
}
textarea {
 max-height: 64px;
 min-width: calc(100% - 10px);
 width: calc(100% - 10px);
 max-width: calc(100% - 10px);
 white-space: initial !important;
}
<h1 style="text-align:center">CSS sqrt function generator</h1>
<nthText>Nth root: <input id="nth" type="text" placeholder="2" value="2" /><br /></nthText>
Percision: <sub>(min)</sub> <input id="percision" type="range" min="1" max="20" value="5" /> <sub>(max)</sub> (<span id="counter">5</span> repetitions)<br />
CSS to be rooted: <input id="input" type="text" placeholder="calc(calc(5vw * 5vh) - 3em)" value="calc(calc(5vw * 5vh) - 3em)" /><br />
<textarea id="output" resize="x" rows="4" onclick="this.select()"></textarea><br />
(click on the textarea above and press <b>Ctrl</b><small>+</small><b>C</b> to copy)

Browser Support for this method: IE9+ (because all that is needed is the calc function)