在 css 计算函数中使用模数

Using modulus in css calc function

有什么方法可以在 css 计算函数中使用或实现 modulus 运算符?
我知道有 mod 运算符并且 IE 支持它,但是其他浏览器呢?

例如

#element-id{
     width: calc( 100%  mod 5 );
}

干脆...“不”。

MDN

The expression can be any simple expression combining the following operators, using standard operator precedence rules:

+ Addition.

- Subtraction.

* Multiplication. At least one of the arguments must be a <number>.

/ Division. The right-hand side must be a <number>.

恐怕只有 Internet Explorer 支持 mod 功能,而且已经 dropped from the CSS spec,因此其他浏览器不太可能很快支持它。

遗憾的是,recent specs中不再提及mod运算符。

The calc() function allows mathematical expressions with addition (+), subtraction (-), multiplication (*), and division (/) to be used as component values.

您可能希望使用 javascript 来实现这种行为。

var el = document.getElementById('element-id');
el.style.width = (100 % 5) + '%';

浏览器不再支持此运算符。 您只能将 标准操作 与计算一起使用:

  • 加法+
  • 减法-
  • 乘法*
  • 除法/

calc() article 提供了对该功能的进一步详细说明。

如果您动态生成 CSS,我创建了一个小的 class 来执行简单的函数,例如 abs()、ceil()、floor()、mod() 和sign() -- 它可用于构建复杂的计算规则,您可以将这些规则作为参数传递给彼此。如果您使用“var(--my-variable)”作为参数,将使用 CSS 变量。 注意:它最适合原始数字,并且有一个实用函数 toUnit 可以在最后转换为像素(等)。

可以这样调用,jquery以设置样式为例:

 $('#my-element').css('width', `${cssHack.toUnit(cssHack.mod(254,25),'px')}`)

下面是 class 的代码(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}) `);
    }
}

好吧,它支持 4 个东西; /*+-。 我们只需要一些数学。

我们试试,10 除以 5。 要得到余数,我们需要从“被除数”中减去“除数与商的乘积”。 10 / 5 会给我们商数,这足以让我们解决问题。

--dividend = 10;
--divisor = 5;

// 10 - (5 * (10 / 5))
// 10 - (5 * 2)
// 10 - 10
// 0

让我们用 15 除以 2 再试一次。

--dividend = 15;
--divisor = 2;

// 15 - (2 * (15 / 2))
// 15 - (2 * 7)
// 15 - 14
// 1

所以,会是这样的……

calc(var(--dividend) - (var(--divisor) * (var(--dividend) / var(--divisor))));

仅供参考,+- 运算符必须用空格包围。但在运算符前后使用空格是一个好习惯。 See here for more.

CSS 值和单位模块级别 4 (W3C 工作草案,2022 年 4 月 27 日)有 mod() (general information about CSS4 at Wikipedia).

截至撰写本文时(2022 年 4 月),此功能太新了,尚无浏览器支持;事实上,它是如此新鲜,以至于 Can I use 都没有条目。将来,Can I use 可能会在 https://caniuse.com/mod.

有专门的 mod() 页面

虽然目前不支持 mod(),但可以通过其他 CSS 功能[=76] 实现 取模运算 =],如 https://css-tricks.com/using-absolute-value-sign-rounding-and-modulo-in-css-today:

中所示
@property --floor {
  syntax: '<integer>';
  initial-value: 0;
  inherits: false;
}

.a-mod-b-width {
  background-color: yellow;
  --floor: calc(var(--a)/var(--b) - 0.5);
  --mod: calc(var(--a) - var(--b)*var(--floor));
  width: calc(100px * var(--mod));
}

此技术利用 calc() and @property, albeit @property having limited browser support as well as of this writing: Therefore, this technique works in Chrome, Edge, and Opera; but it currently does not work in Firefox and Safari. The main trick is to define a CSS property --floor with "syntax" <integer>, which calculates values using the floor function. Having a floor function available this way, a mod b is calculated in the --mod property using the function a - b * floor(a / b)

以下演示使用此技术计算其某些 divwidth

  • 在第 1 到 4 行中,right-column div 有 hard-coded width;这里没有 modulo 魔法。它们的目的是作为与 计算宽度的 div 进行比较的参考。请注意,第一个“绿色”div 由于其 width: 0px.
  • 实际上是不可见的
  • 从第 5 行开始,黄色的 right-column div 根据规则 100px * (a mod 3) 计算它们的宽度,值 a=[0, 1, 2, 3, 4]。由于 0 mod 33 mod 3 等于 0,它们的 div 宽度为 0px,因此实际上是不可见的。

.grid-container {
  display: grid;
  grid-template-columns: auto auto;
  background-color: lightgray;
  grid-gap: 10px;
}

.grid-container > *:nth-child(2n + 1) {
  background-color: silver;
  font-family: monospace;
}

.green {
  background-color: green;
  width: 0px;
}

.aqua {
  background-color: aqua;
  width: 100px;
}

.orange {
  background-color: orange;
  width: 200px;
}

.red {
  background-color: red;
  width: 300px;
}

@property --floor {
  syntax: '<integer>';
  initial-value: 0;
  inherits: false;
}

.a-mod-b-width {
  background-color: yellow;
  --floor: calc(var(--a)/var(--b) - 0.5);
  --mod: calc(var(--a) - var(--b)*var(--floor));
  width: calc(100px * var(--mod));
}

.a0 {
  --a: 0;
}

.a1 {
  --a: 1;
}

.a2 {
  --a: 2;
}

.a3 {
  --a: 3;
}

.a4 {
  --a: 4;
}

.a5 {
  --a: 5;
}


.b0 {
  --b: 0;
}

.b1 {
  --b: 1;
}

.b2 {
  --b: 2;
}

.b3 {
  --b: 3;
}

.b4 {
  --b: 4;
}
<div class="grid-container">
  <div>width: 0px (green)</div>
  <div class="green"></div>
  
  <div>width: 100px (aqua)</div>
  <div class="aqua"></div>
  
  <div>width: 200px (orange)</div>
  <div class="orange"></div>
  
  <div>width: 300px (red)</div>
  <div class="red"></div>

  <div></div>
  <div></div>
  <div></div>
  <div></div>
  
  <div>width: 100px * (0 mod 3)</div>
  <div class="a0 b3 a-mod-b-width"></div>
  
  <div>width: 100px * (1 mod 3)</div>
  <div class="a1 b3 a-mod-b-width"></div>
  
  <div>width: 100px * (2 mod 3)</div>
  <div class="a2 b3 a-mod-b-width"></div>
  
  <div>width: 100px * (3 mod 3)</div>
  <div class="a3 b3 a-mod-b-width"></div>
  
  <div>width: 100px * (4 mod 3)</div>
  <div class="a4 b3 a-mod-b-width"></div>
  
  <div>width: 100px * (5 mod 3)</div>
  <div class="a5 b3 a-mod-b-width"></div>
</div>

除了有限的浏览器支持之外,使用这种计算模数技术还有一个可能的注意事项:"The Chrome browser currently won't accept some values returned by calc() when an integer is expected. This includes any division, even if it results in an integer. ie. z-index: calc(4 / 2); will not be accepted."