OVERHEAD

If-set logic for variables in CSS

CSS

Conditional logic

Let’s say we have a rule set like this:

A basic CSS rule set where some element “element” is given padding-top: 2rem.

element {
	padding-top: 2rem;
}

Now, let’s introduce a variable called --add-padding. When the variable is set, we want the value of padding-top to change from 2rem to 4rem, however, --add-padding could be any arbitrary non-zero value (so we can’t do calc( 2rem + var(--add-padding) )). This is how you could construct this logic:

A modification to the previous CSS rule set, where --add-padding being set or not controls the value of padding-top.

element {
	padding-top: calc(
		2rem + (
			2rem *
			( var(--add-padding, 0) / var(--add-padding, 1) )
		)
	);
}
  • When --add-padding is set, var(--add-padding, 0) / var(--add-padding, 1) will always return 1 since it’s just the variable’s value divided by itself. This simplifies the calculation to 2rem + ( 2rem * 1 ) which is 4rem.
  • When --add-padding is unset, var(--add-padding, 0) / var(--add-padding, 1) becomes 0 / 1 which returns 0. This simplifies the calculation to 2rem + ( 2rem * 0 ) which is 2rem.

You can also change the variables’ fallback values to achieve different behaviour, e.g. 1rem + ( 3rem * ( var(--add-padding, 2) / var(--add-padding, 1) ) ) will return 4rem when --add-padding is set, but 7rem when it’s unset.

It’s important you divide zero by one and not itself. For those unaware of the reason, the next section will explain why.

Zero is weird

The handling of zero in CSS calc functions can be unintuitive at first. Take the following calculation as an example:

calc( 2rem + ( 2rem * ( 0 / 0 ) ) )

You might assume this function returns 2rem, but in reality, it returns 0. This is because any operation involving invalid values will in turn respond with an invalid value including addition and subtraction, so 2rem * INVALID is invalid and 2rem + INVALID is also invalid. For the assumed result, use zero divided by one (0 / 1) instead.

It’s important to stress that this behaviour is not invalidating the whole function, therefore, if we put this calculation inside the max function:

max( 1rem, 2rem + ( 2rem * ( 0 / 0 ) ) )

This will return 1rem, as only the zero-zero side of the calculation returns an invalid value, and the rest of the function works independently.