Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css calc - round down with two decimal cases

Tags:

css

sass

css-calc

I have the following situation:

div {
    width: calc((100% / 11) - 9.09px);
}

In the context, 100% = 1440px, and 9.09px is generated in mathematics with sass.

The results is: 94.55px, because calc rounds it up, but I need 94.54px (round down).

How can I round down to the nearest hundredths place?

Edit: example.

like image 501
Cleiton Souza Avatar asked Jun 10 '16 17:06

Cleiton Souza


3 Answers

In general I would say that it's not possible, but there's a hack. However in the web, hacks seem to be the norm, instead of the exception, so I'll just say that it is possible:

div {
    --shf: 4.9406564584124654e-322;
    width: calc(((100% / 11) - 9.09px) * var(--shf) / var(--shf));
}

What this does: it multiplies the value to be rounded by a really small value that underflows the value starting at the third decimal point. Then, it divides the truncated value back, resulting in a rounded version of the value. This assumes that all browsers you support use 64-bit floating point values. If they don't, not only this will be wrong, it might return zero when using smaller floating point data types, completely breaking your page.

Change the exponent to -323 to round at the first decimal point and -324 to round at integer values.

like image 168
hdante Avatar answered Oct 16 '22 18:10

hdante


Unfortunately, there is not a native way in CSS to round (or ceil/floor) numbers.

However — you mentioned you are using Sass. I found a small Sass library that can round, floor, and ceil numbers to a specified precision.

For example, if you had a had 94.546 you could use decimal-floor(94.546, 2) which would return 94.54.

Unfortunately, this might not help if you have to use calc() to calculate on the fly with CSS. However, if you can pre-calculate the width and floor it with Sass it would fit your needs. A possible solution could be using @media queries as a way to set breakpoints and use those breakpoints in your Sass preprocessing.

like image 16
pinjasaur Avatar answered Oct 16 '22 18:10

pinjasaur


If you dynamically generate your CSS, I created a small class to do simple functions like round(), ceil(), floor(), abs(), mod() and sign() -- it can be used to build complex calc rules which you can pass to each other as arguments. If you use "var(--my-variable)" as a parameter, the CSS variable will be used. Note: it works best with raw numbers and has a utility function toUnit to convert to pixels (etc) at the end.

you can call it like so, jquery as an example to set the style:

 $('#my-element').css('width', `${cssHack.toUnit(cssHack.round(1000/3),'px')}`)

Below is the code for the class (es6, no dependencies):

class cssHack
{
    //primary used for dynamic css variables-- pass in 'var(--dynamic-height)'
    static toUnit(val,unit)
    {
        unit='1'+unit;
        return ` calc(${val} * ${unit}) `;
    }

    static round(val)
    {
        // the magic number below is the lowest possible integer, causing a "underflow" that happily results in a rounding error we can use for purposeful rounding.
        return ` calc(${val} * ${Number.MIN_VALUE} / ${Number.MIN_VALUE}) `;
    }

    static abs(val)
    {
        return ` max(${val}, calc(${val} * -1)) `;
    }

    static floor(val)
    {
        return cssHack.round(` calc(${val} - .5) `);
    }

    static ceil(val)
    {
        return cssHack.round( `calc(${val} + .5) `);
    }

    static sign(val)
    {   
        let n = ` min(${val},0) `; //if val is positive then n =0. otherwise n=val.
        let isNegative= ` min(${cssHack.ceil(cssHack.abs(n))},1) `;
        let p = ` max(${val},0) `; //if val is negative then n=0, otherwise n = val;
        let isPositive= ` min(${cssHack.ceil(cssHack.abs(p))},1) `;
        return ` calc(${isPositive} + calc(${isNegative} * -1)) `;
    }

    static mod(val, base)
    {
        let abs = cssHack.abs(val);
        let div = ` calc(${abs} / ${base})`;
        let dec = ` calc(${div} - ${cssHack.floor(div)})`;
        return cssHack.round(` calc(${dec} * ${base}) `);
    }
}
like image 2
Joe Love Avatar answered Oct 16 '22 18:10

Joe Love