css calc -四舍五入,保留两位小数

ma8fv8wu  于 2022-12-01  发布在  其他
关注(0)|答案(6)|浏览(1290)

我有以下情况:

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

在上下文中,100% = 1440px,而9.09px在数学上是用sass生成的。
结果是:94.55px,因为 calc 将其向上舍入,但我需要94.54px(将其向下舍入)。
我怎么能***四舍五入***到最接近的百分之一位?

编辑:example

k3fezbri

k3fezbri1#

一般来说我会说这是不可能的,但有一个黑客。然而在网络,黑客似乎是常态,而不是例外,所以我只会说这是可能的:

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

它的作用:它把要舍入的值乘以一个非常小的值,该值从第三个小数点开始下溢,然后,它把截断的值除以,得到舍入后的值。这假定您支持的所有浏览器都使用64位浮点值。如果它们不使用,不仅会出错,而且在使用更小的浮点数据类型时,它可能返回零,完全破坏你的页面。
将指数更改为-323以舍入到第一个小数点,更改为-324以舍入到整数值。

d7v8vwbk

d7v8vwbk2#

不幸的是,CSS中没有对数字进行舍入(或取整/取整)的原生方法。
然而-你提到你正在使用Sass。我找到了一个small Sass library,它可以将数字取整、取底和取整到指定的精度。
例如,如果您有94.546,您可以使用decimal-floor(94.546, 2),它会传回94.54
不幸的是,如果您必须使用calc()来使用CSS进行动态计算,这可能没有帮助。但是,如果您可以预先计算width,并使用Sass对其进行floor,这将满足您的需要。一个可能的解决方案是使用@media查询作为设置断点的一种方式,并在Sass预处理中使用这些断点。

ao218c7q

ao218c7q3#

如果你动态生成CSS,我创建了一个小类来执行简单的函数,比如round()、ceil()、floor()、abs()、mod()和sign()--它可以用来构建复杂的计算规则,你可以把它们作为参数传递给其他人。如果你使用"var(--my-variable)"作为参数,那么就使用CSS变量。注意:它最适合处理原始数字,并有一个实用函数toUnit在最后转换为像素(等)。
你可以这样调用它,以jquery为例来设置样式:

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

下面是该类的代码(es6,无依赖项):

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}) `);
    }
}
7jmck4yq

7jmck4yq4#

如果您的问题是一个像素舍入误差相关的视觉差异,在大多数情况下,您实际上不需要舍入。一个相对简单的解决方案是使您的一个项目占据所有剩余的空间。
在Flex方案中,如果您不需要布局换行,您甚至可以选择一个中心项目,以获得最不明显的效果。

.some-block {
    width: calc( ( 100% / 11 ) - 9.09px );
    flex-shrink: 0;
}

.some-block:nth-of-type(5) {
    // Will attempt to take the whole width, but its siblings refuse to shrink, so it'll just take every bit of remaining space.
    width: 100%;
}

根据具体的CSS情况,可以通过使用填充或边距以及一个额外的嵌套元素来完全避免像素减法。这样,CSS calc()就变得无关紧要了,这一切都可以在Sass中完成,Sass有更强大的数学工具,并且不需要客户端进行计算。
此外,在弹性上下文中,如果您的目标只是使每个元素相等,则可能根本不需要计算。有关详细信息,请参阅this question
在表格中,由于单元格宽度是从左到右计算的,因此可以使用类似的技巧,但您必须为 last 单元格指定width: 100%,因为没有flex-shrink的概念,列宽是从左到右确定的。

.my-table {
    table-layout: fixed;
}

.table-cell {
    width: calc( ( 100% / 11 ) - 9.09px );
}

.table-cell:last-of-type {
    // Will attempt to take the whole width, but since previous column widths have already been determined, it cannot grow any further than its allocated width plus any stray pixels.
    width: 100%;
}
xn1cxnb4

xn1cxnb45#

既然你已经用过了,试试它圆形、地板和天花板的方法:https://sass-lang.com/documentation/modules/math#bounding-functions
(also在sass的较早版本中,使用不同的语法)

mzmfm0qo

mzmfm0qo6#

round() CSS函数

CSS值和单位模块级别4 中,您可以使用**round() CSS函数**对数字或维度进行任意舍入。

round(<rounding-strategy>, valueToRound, roundingInterval)

可选的rounding-strategy可以是updownnearest(默认)和to-zero之一,它们分别对应于Javascript中的Math.ceilMath.floorMath.roundMath.trunc

示例

若要将<canvas>元素的大小调整为 almost(“舍入间隔为a CSS pixel,不是装置像素。”) 适合其父元素,同时保留画布像素长宽比1:1(假设window.devicePixelRatio是自然数):

canvas {
    display: block;
    width: round(down, 100%, 1px);
    height: round(down, 100%, 1px);
}

浏览器支持

当前为only Safari supports this.

另请参阅

相关问题