I've searched around for an answer to this, but couldn't find any useful information. I'm trying to set the top property of an element in CSS to max(0, 120vh - 271px). I've tried several variations of this:
top: max(0, 120vh - 271px);
top: max(0, (120vh - 271px));
top: max(0, calc(120vh - 271px));
Is there something wrong with my syntax? I keep getting Chrome telling me that this is an invalid property error.
In practice, I'm actually using CSS variables for the numbers. so 120vh is actually var(--height) or something like that. When I use CSS variables, the line just doesn't do anything. It doesn't apply the style, and I don't get any warnings. What am I doing wrong here?
I'm using the newest version of Chrome (83 I believe), so this should be supported.
You need to add a unit to 0 otherwise it's confusing for the browser to handle the comparison between a uniteless value (a <number>) and a value with unit (a <length>) and the top property accept a <length> not a <number>
top: max(0px, 120vh - 271px)
To understand this, you need to follow the specification:
The min() or max() functions contain one or more comma-separated calculations, and represent the smallest (most negative) or largest (most positive) of them, respectively.
Then for calculations:
A calc() function contains a single calculation which is a sequence of values interspersed with operators, and possibly grouped by parentheses (matching the <calc-sum> grammar),
So the content of min()/max() is treated like the one of calc() then from the type checking
A math function can be many possible types, such as <length>, <number>, etc., depending on the calculations it contains, as defined below. It can be used anywhere a value of that type is allowed.
and
Note: Altho there are a few properties in which a bare <number> becomes a <length> at used-value time (specifically, line-height and tab-size), <number>s never become "length-like" in calc(). They always stay as <number>s.
You may get surprised but using top:0 is valid while top:min(0) or top:max(0) is not. To make them valid you need to add the unit.
But you can use opacity: min(0) for example since opacity accept a number as argument.
Worth to note that the same also apply to clamp() since it's equivalent to max(MIN, min(VAL, MAX))
Related: Why doesn't css-calc() work when using 0 inside the equation?
Related
I have searched the internet and it seems very hard to find this info.
When I do
div {
width: calc(1e-10 * 1e12px);
}
It sets the width to 100px. But when I do
div {
width: calc(1e-1000 * 1e1002px);
}
It fails. Clearly, 1e1002 is out of range.
What is the valid range of numbers in CSS? Does it depend on the unit? Is it browser specific?
It is up to each browser to pick limits for CSS real numbers. The spec supports a theoretically infinite range but relies on vendors to provide 'reasonable' support.
4.1. Range Restrictions and Range Definition Notation
Properties can restrict numeric values to some range. If the value is outside the allowed range, then unless otherwise specified, the declaration is invalid and must be ignored.
[...]
CSS theoretically supports infinite precision and infinite ranges for all value types; however in reality implementations have finite capacity. UAs should support reasonably useful ranges and precisions. Range extremes that are ideally unlimited are indicated using ∞ or −∞ as appropriate.
Soruce: https://www.w3.org/TR/css-values-3/#numeric-ranges
See also:
4.3. Real Numbers: the <number> type
Number values are denoted by <number>, and represent real numbers, possibly with a fractional component.
When written literally, a number is either an integer, or zero or more decimal digits followed by a dot (.) followed by one or more decimal digits and optionally an exponent composed of "e" or "E" and an integer. It corresponds to the <number-token> production in the CSS Syntax Module [CSS3SYN]. As with integers, the first character of a number may be immediately preceded by - or + to indicate the number’s sign.
Source: https://www.w3.org/TR/css-values-3/#numbers
Recently I've started using the calc(...) method within CSS. I quickly learned that code such as: width: calc(100%-2) will not work, though adding white-space before and after the - operator will fix the problem and the calc method will function properly.
After doing a bit of research I found multiple blog posts reference that the white-space is required and many have even pointed to the specification (CSS3 8.1.1) which states:
In addition, whitespace is required on both sides of the + and -
operators. (The * and / operaters can be used without whitespace
around them.)
Now, clearly, the spec tells us that these operators must be wrapped in white-space, but why? I've read further within the spec (through sections 8.1.2-4) and if it's explained in these additional portions, I'm not understanding the reasoning.
In simple terms, could someone explain why it was specified that calc(100% - 1) or even calc(100%/2) is acceptable syntax but not calc(100%-1)?
The - character is one of the allowed characters in CSS idents. Judging by the resolution given here, it seems they wanted to prevent syntactic ambiguities that could arise from using - without whitespace, especially with keyword values such as min-content (although AFAIK keyword values aren't yet allowed within calc() — correct me if I'm wrong).
Not everyone agrees with this resolution, though.
The Mozilla Developer Network explains it quite well:
Note: The + and - operators must always be surrounded by whitespace. The operand of calc(50% -8px) for instance will be parsed as a percentage followed by a negative length, an invalid expression, while the operand of calc(50% - 8px) is a percentage followed by a minus sign and a length. Even further, calc(8px + -50%) is treated as a length followed by a plus sign and a negative percentage.
The * and / operators do not require whitespace, but adding it for consistency is allowed, and recommended.
I think you should first consider how do CSSs identify a length. A length is defined as an optional sign followed by a module and an optional unit of measure (although many properties actually require it):
<CSSlength> := [<sign>]<module>[<unit>]
So, for example, valid CSS lengths are:
-3px
100em
+10pc
0
91
5%
Defining a length like this, the CSS engine parses the following:
calc(100% -1px);
as a length followed by another length. In this case it would be 100% followed by -1px, which doesn't make sense to calc() at all. This is also explained in the relative MDN documentation page.
In order to put two lengths in relation you need to use a distinct operator, therefore, following the above logic, you'll need to use whitespaces:
calc(100% - 1px);
Can someone tell me why this CSS calc function isn't working? When I inspect element on Chrome, it says 'Invalid property value'.
width: calc((100vw - 14px * 2) / (270px + 11px * 2));
For future googlers:
The unhelpful "invalid property value" message in DevTools might just mean that you need white space around your + - / * operators.
Incorrect (invalid property value):
width:calc(100vh-60px) <== no spaces around minus sign
Correct:
width:calc(100vh - 60px) <== white space around the minus sign
The OP's question above does not have this problem, but while googling an answer to this error message this is the first resource I found, so it should have an answer dedicated to this common error.
References:
CSS3 calc() not working in latest chrome
https://www.smashingmagazine.com/2015/12/getting-started-css-calc-techniques/
You can't divide by units like px, only numbers.
When using calc() you can't divide by pixels, you can only divide by unitless numbers. Also, the number you are dividing has to have a certain unit like px, em, vh, vw.
For example, if you need to set a width of an element you should use:
width: (100px / 2); //this equals to 50px
An important note is to make sure you put spaces between the operator signs. This calc() article provides further detailed explanation on the function.
As #cssyphys noted above, you have to have spaces around your minus sign. However, if you are using ASP.NET MVC's bundler/minifier you find that it removes the spaces so you get the noted error.
If you are using plain CSS3, the following expression can be used in CSS and won't get minified:
width: calc((100%) - 50px);
HOWEVER, if you are using LESS (and perhaps other CSS preprocessors?), the preprocessor will "optimize" your expression and rip out your inner parens, again resulting in something ASP.NET will botch up. To get around that, use LESS's "don't process" tilde expression:
width: calc(~"(100%) - 50px");
I had to go back and change a bunch of calc() statements but so worth it to get back my ASP.NET minification.
As Stephen Thomas has answered, you can't divide by units. To get around this, just divide the numbers as numbers and then assign the unit of measurement by multiplying the result by 1 unit of the units you're interested in. In your nested scenario you'd need to figure out what unit of measurement you were after in the end so that you could divide the numbers and then assign the result to a px or vw unit of measurement.
I just came across this error because one SCSS variable was set to zero:
WRONG:
$card-border-width: 0;
This eventually provoked Chrome's message Invalid property value in answer to the CSS result border-radius: 0 0 calc(0.25rem - 0) calc(0.25rem - 0).
RIGHT:
$card-border-width: 0rem;
(giving border-radius: 0 0 calc(0.25rem - 0rem) calc(0.25rem - 0rem))
Suppose, I am creating an image gallery; at a certain device width, there will be three images, hence, I need to work out one third:
{width:calc(100% / 3)}
However, the issue is that I need to take away '2px' (two pixels) - I added a margin of 1px, hence this needs to be accounted for by taking this away from the width, hence I need to do:
{width:calc(calc(100% / 3) - 2px)}
But, this does not work: is there a way I can do this?
[I need to work out a third, then take two pixels away from this -- it is messy because a third is difficult to format as a percentage.]
For the sake of completeness, I will add an answer here (The solution has already been posted in the comments underneath the asker's question).
You don't need to use two calc() statements. It's sufficient for you to combine the calculations within one calc() statement. In this case, as Andrea Ghidini mentioned in a comment (refer to this link), the division will take precedence over the subtraction (basic math rules apply!).
So your solution would be:
width:calc(100% / 3 - 2px)
Also, make sure that additions and subtractions are surrounded by whitespaces, otherwise it will not work!
Can I change the default unit from pixel to mm?
For example I want when move an element left and top to be in mm not in pixel?
There is no 'default unit'. The CSS spec requires that a length (other than zero) that is missing a unit be treated as an error (and thus ignored).
In quirks mode (and you should almost never be using quirks mode, it makes life more difficult), most browsers will perform error recovery and assume you meant pixels (despite the spec forbidding this).
From the standard:
A <quirky-length> is syntactically identical to a <number-token>, and is interpreted as a 'px' length with the same value.
(In other words, Quirks Mode allows all 'px' lengths in the affected properties to be written without a unit, similar to unitless zero lengths.)
If you are working with screen media — avoid physical units. Most systems are not calibrated to calculate the DPI correctly (so when converting from physical units into something a monitor understands (pixels) they get it wrong).
Specifying CSS units is a requirement for non-zero values. Browsers may try to guess what you meant, but it would still be a broken stylesheet according to the standard.
I.e. there is no "default unit" in CSS2, it's just that the browser may try to help you out, although it may as well just ignore your statement that doesn't specify units as an invalid one.
No, you can not change the default unit, but it shouldn't be too much to just put the units there:
#foo {
left: 22mm;
top: 20mm;
}
You should always specify the unit nevertheless, because it is required and browsers might interpret unitless values differently.
As there's no "default unit" and you need to provide the unit when positioning an element, you can just use "mm" instead of "px".
AFAIK if no explicit unit was specified (like 'em' or '%') then "px" is concatenated to the value and there is no way to override this default behavior.
Yes, You can do this indirectly by assigning variable for unit:
--unit: 1mm;
--value: 10;
--variable: calc(var(--unit) * var(--value));
No, that's not possible since different screens might have different sizes while still having the same resolution. Ultimately leading to pixel or relative notations.