Using modulus in css calc function
Asked Answered
P

9

26

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 );
}
Postboy answered 23/12, 2015 at 12:5 Comment(2)
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.Repulsive
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?Esoterica
E
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) + '%';
Elsewhere answered 23/12, 2015 at 12:11 Comment(0)
S
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>.

Sulemasulf answered 23/12, 2015 at 12:11 Comment(0)
A
6

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

Adjudicate answered 29/4, 2022 at 23:44 Comment(1)
Of course the article is by Ana Tudor... 😆Induna
G
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.

Garrulity answered 17/5, 2018 at 13:17 Comment(0)
H
1

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.

Housebreak answered 4/3, 2022 at 11:53 Comment(3)
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 IntegersScutter
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.Housebreak
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.Scutter
N
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.

Nam answered 23/12, 2015 at 12:11 Comment(3)
Do you have a reference that IE supports or supported the mod function? It doesn't seem to work now.Wadsworth
Unfortunately not. Sorry. I can't even recall which version I was referring to :-/Nam
That's too bad. Post if you ever find it or remember.Wadsworth
E
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}) `);
    }
}
Esoterica answered 11/11, 2021 at 18:6 Comment(0)
U
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.

Upandcoming answered 27/6, 2022 at 18:40 Comment(4)
Please provide an explanation to your code - it is very hard to understand something when it isn't explained.Stinker
These are the features used: - CSS variables: W3Schools Article - 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.Upandcoming
For example, I could have the javascript document.documentElement.style.setProperty(‘--elementWidth’, ‘300px’), and in CSS: #elementID { width: var(--elementWidth); }.Upandcoming
Here's the cssTricks article I found it on.Upandcoming
I
0

this formula works for me :

   @temp :(@value - (2 * (floor(@value / 2))));

  if(@temp > 0, rgba(200, 200, 200, 0.20), rgba(100, 100, 100, 0.20)) ;

floor method help to remove decimal part of number and then final result can be checked if divisible to number 2 or not

Idler answered 19/5 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.