24

Is there any way to use or implement modulus operator in css calc function?
I know there is mod operator and IE supports it, but what about other browsers?

For example

#element-id{
     width: calc( 100%  mod 5 );
}
dippas
  • 58,591
  • 15
  • 114
  • 126
Hike Nalbandyan
  • 994
  • 1
  • 11
  • 28
  • 1
    No way.. If you serve your html file via a PHP server (for example), put the style inside the html markup instead. That way will let you compute this. – David Dec 23 '15 at 12:10
  • What would 100% mod 5 be anyway? 100 mod 5 would always be zero-- but I think you're expecting 100% to be converted to pixels before the "mod 5" happens.. so for example if it's 304 pixels wide, the width would wind up being 4px after mod by 5? – Joe Love Nov 11 '21 at 18:02

8 Answers8

14

Unfortunately, there is no more mention of the mod operator in recent specs.

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

You may want to resort to using javascript to achieve such behaviour.

var el = document.getElementById('element-id');
el.style.width = (100 % 5) + '%';
Gerrit Bertier
  • 4,101
  • 2
  • 20
  • 36
8

Simply..."NO".

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>.

Community
  • 1
  • 1
Paulie_D
  • 107,962
  • 13
  • 142
  • 161
5

CSS Values and Units Module Level 4 (W3C Working Draft, 27 April 2022) has mod() (general information about CSS4 at Wikipedia).

As of this writing (April 2022), this feature is so new that no browser supports it yet; in fact, it's so fresh that even Can I use doesn't have an entry for it. In the future, Can I use will probably have a dedicated page for mod() at https://caniuse.com/mod.

While there currently is no support for mod(), the modulo operation can be achieved with other CSS features, as presented in 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));
}

This technique leverages 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).

The following demo uses this technique to calculate the width of some of its divs:

  • In rows 1 to 4, the right-column divs have hard-coded width; no modulo magic here. Their purpose is to act as references for comparison to the divs with modulo-calculated width. Note that the first, "green", div is effectively invisible due to its width: 0px.
  • From row 5 onwards, the right-column divs, colored yellow, calculate their width according to the rule 100px * (a mod 3), for values a=[0, 1, 2, 3, 4]. Due to 0 mod 3 and 3 mod 3 equaling 0, their divs have a width of 0px and are therefore effectively invisible.

.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>

Besides the limited browser support, there is another possible caveat in using this calculated modulo technique: "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."

Abdull
  • 26,371
  • 26
  • 130
  • 172
1

This operator is no longer supported in browsers. You can only use standard operations with calc:

  • addition +
  • subtraction -
  • multiplication *
  • division /

This calc() article provides a further detailed explanation on the function.

Chris
  • 57,622
  • 19
  • 111
  • 137
Nesha Zoric
  • 6,218
  • 42
  • 34
0

Only Internet Explorer supports the mod function, I'm afraid, and it has been dropped from the CSS spec, so other browsers are not likely to support it any time soon.

Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
0

If you dynamically generate your CSS, I created a small class to do simple functions like abs(), ceil(), floor(), 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.mod(254,25),'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}) `);
    }
}
Joe Love
  • 5,594
  • 2
  • 20
  • 32
0

Well, it supports 4 things; /, *, +, -. And we just need a few maths.

Let's try, 10 divided by 5. To get the remainder, we need to subtract "the multiplication of divisor and quotient" out of "the dividend." 10 / 5 will give us the quotient and that's enough for us to work things around.

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

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

Let's try again with 15 divided by 2.

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

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

So, it will be like this...

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

FYI, + and - operators must be surrounded by whitespace. But it's a good practice to use whitespace before and after the operator. See here for more.

  • 1
    Apparently this only works when the css property accepts integer values, Otherwise result of `calc(15 / 2)` is `7.5` not `7`. [MDN: Usage with Integers](https://developer.mozilla.org/en-US/docs/web/css/calc#usage_with_integers) – ufukty Apr 26 '22 at 16:40
  • 1
    Oh, yeah. You're right! It will become 15-16 and get -1. Sorry, my bad. Just like they said above we got no option but to use JavaScript for that. – Aye Chan Aung Thwin Apr 27 '22 at 17:37
  • Thats ok, it works in some cases. Plus, idea has potential for more too. [You just need to multiply/divide with smallest/biggest value to take advantage of overflow.](https://stackoverflow.com/a/64921523/10272920) – ufukty Apr 27 '22 at 20:02
0

My recommendation would be to use JavaScript to set document.documentElement.style.setProperty(‘--variable’, ‘value’) so that you can do the math in JS and use the variable in css.

bztravis
  • 11
  • 4
  • Please provide an explanation to your code - it is very hard to understand something when it isn't explained. – ethry Jul 02 '22 at 21:21
  • These are the features used: - CSS variables: [W3Schools Article](https://www.w3schools.com/css/css3_variables.asp) - The Javascript code segment: this accesses the HTML tag and assigns CSS variables values, which effectively gives the CSS access to the values assigned from Javascript. – bztravis Jul 04 '22 at 02:43
  • For example, I could have the javascript `document.documentElement.style.setProperty(‘--elementWidth’, ‘300px’)`, and in CSS: `#elementID { width: var(--elementWidth); }`. – bztravis Jul 04 '22 at 02:45
  • Here's the [cssTricks article](https://css-tricks.com/updating-a-css-variable-with-javascript) I found it on. – bztravis Jul 04 '22 at 02:56