Whitespace in CSS Calculations
Published 12 years, 8 months pastI’ve been messing around with native calculated values in CSS, and there’s something a bit surprising buried in the value format. To quote the CSS3 Values and Units specification:
Note that the grammar requires spaces around binary ‘+’ and ‘-’ operators. The ‘*’ and ‘/’ operators do not require spaces.
In other words, two out of four calculation operators require whitespace around them, and for the other two it doesn’t matter. Nothing like consistency, eh?
This is why you see examples like this:
width: calc(100%/3 - 2*1em - 2*1px);
That’s actually the minimum number of characters you need to write that particular expression, so far as I can tell. Given the grammar requirements, you could legitimately rewrite that example like so:
width: calc(100% / 3 - 2 * 1em - 2 * 1px);
…but not like so:
width: calc(100%/3-2*1em-2*1px);
The removal of the spaces around the ‘-’ operators means the whole value is invalid, and will be discarded outright by browsers.
We can of course say that this last example is kind of unreadable and so it’s better to have the spaces in there, but the part that trips me up is the general inconsistency in whitespace requirements. There are apparently very good reasons, or at least very historical reasons, why the spaces around ‘+’ and ‘-’ are necessary. In which case, I personally would have required spaces around all the operators, just to keep things consistent. But maybe that’s just me.
Regardless, this is something to keep in mind as we move forward into an era of wider browser support for calc()
.
Oh, and by the way, the specification also says:
The ‘calc()’ expression represents the result of the mathematical calculation it contains, using standard operator precedence rules.
Unfortunately, the specification doesn’t seem to actually define these “standard operator precedence rules”. This makes for some interesting ambiguities because, as with most standards, there are so many to choose from. For example, 3em / 2 * 3
could be “three em divided by two, with the result multiplied by three” (thus 4.5em) or “three em divided by six” (thus 0.5em), depending on whether you privilege multipliers over dividers or vice versa.
I’ve looked around the Values and Units specification but haven’t found any text defining the actual rules of precedence, so I’m going to assume US rules (which would yield 4.5em) unless proven otherwise. Initial testing seems to bear this out, but not every browser line supports these sorts of expressions yet, so there’s still plenty of time for them to introduce inconsistencies. If you want to be clear about how you want your operators to be resolved, use parentheses: they trump all. If you want to be sure 3em / 2 * 3
resolves to 4.5em, then write it (3em / 2) * 3
, or (3em/2)*3
if you care to use inconsistent whitespacing.