Open David263 opened 2 months ago
It can be anything. margin: calc(1em + 1em)
gives you margin: 2em
(which will resolve to px based on the font-size
). margin: calc(1px + 1px)
gives you margin: 2px
. flex: calc(1 + 1)
gives you flex: 2
. There's no restrictions on what the result's type must be.
What is the result type of calc(1rem + 1px)? What is the result type of calc(1px + 1rem)? My claim is that the result datatype is undefined in the document.
There is nothing more granular in CSS than <length>
. The answer is that 1px
represents a physical length and 1rem
also represents a physical length, so the result is whatever those two lengths add up to. In fact, all length units you use in CSS are underlyingly the same thing—just that they are relative to different units.
Think about this way: what's 1 meter + 1 inch? Is the result in meters or inches? The answer is it doesn't matter because you can write it both ways and get the same physical meaning.
So how is <length>
represented in the computer? Is it a single-precision floating point number? If it is, then the document should be specific in saying that the result of calc
is an internal IEEE real number, rounded to an integer (apparently), that represents a length value. In other words, a similar datatype to px
. Thus, calc
can be nested in calc
expressions just like px
values can.
If it is, then the document should be specific in saying that the result of calc is an internal IEEE real number, rounded to an integer (apparently)
It's not an integer if you have any unit—1
and 1px
are two entirely different types in CSS. Every length is underlyingly px
, because that's what actually matters to the computer when it draws on the screen. It can be a fractional pixel value—many devices can have subpixel graphics. You can retrieve the actual used value using getComputedValue
, and you will get a value in px
. Anything deeper than saying "lengths are fundamentally numbers of pixels" would be poking into the implementation details, which we are not interested in—CSS is a declarative high level language and talking about how it's represented in the computer doesn't help.
I don't think the information about "it's always px
" is relevant for calc
either. If you specify width: 1rem
, it's also going to resolve to px
when you retrieve the computed value; that's just how absolute lengths work.
About nested calc: we already mention this:
It is permitted to nest calc() functions, in which case, the inner ones are treated as simple parentheses.
Maybe @estelle can decide what's worth to be added to this page.
I have no idea who estelle is. So, you seem to finally admit that calc
in fact does have a result value, and that it cannot be fundamentally different from some integer number of pixels. You don't seem to realize that the DOM keeps track of pixel distances to a fairly precise fraction of a pixel. (Precision means the number of decimal places in IEEE arithmetic.) So, if calc
really rounds to an integer, it may not be as useful to the user as they hope or expect that it is. That much (the rounding) is already spelled out in the document.
So, we've come around in a circle to my original surmise, which was that calc
generates a result in the px
datatype, even if the expression is calc(1.23245rem)
.
This is the information I'd like to see added to the documentation, as I said in the OP, because currently nothing is said clearly about what the result of calc
really is, as a datatype.
Perhaps you enjoy arguing, but I do not. You could have simply agreed from the start.
px
is not a datatype. <length>
is. I'm saying the entire assumption that there's anything different about rem
and px
is misleading, because width: 1.23245rem
and width: calc(1.23245rem)
are exactly equivalent and both will result in "a length value"—and CSS uses px
as the canonical unit for lengths. calc
doesn't change how length units work. It's like asking whether "1m + 1in" results in "a value of type meters" or "a value of type inch"—the answer is that it doesn't matter, it's just a length. The computer just happens to measure everything in meters but that's an implementation detail unrelated to how calc
works.
You don't seem to realize that the DOM keeps track of pixel distances to a fairly precise fraction of a pixel. (Precision means the number of decimal places in IEEE arithmetic.) So, if
calc
really rounds to an integer, it may not be as useful to the user as they hope or expect that it is.
I explicitly said that "It can be a fractional pixel value" in my last comment and I have verified it with the following code:
<div style="width: 15.5px" id="a"></div>
<div style="width: calc(15px + 0.5px)" id="b"></div>
<script>
console.log(getComputedStyle(document.getElementById('a')).width);
console.log(getComputedStyle(document.getElementById('b')).width);
</script>
Both of them print 15.5px
, so I don't know where the claim that it rounds the value comes from.
By the way, here's what I was saying when I said everything is px
:
<div style="width: 1rem" id="a"></div>
<div style="width: calc(1rem)" id="b"></div>
<div style="width: calc(1rem + 1rem)" id="c"></div>
<script>
console.log(getComputedStyle(document.getElementById('a')).width);
console.log(getComputedStyle(document.getElementById('b')).width);
console.log(getComputedStyle(document.getElementById('c')).width);
</script>
They print 16px
, 16px
, and 32px
, respectively. Non-px
units simply do not exist beyond the CSS source code.
Also the question of "what's the result type of calc
" is also not "it's a <length>
". As I said from the start, it's whatever the operands' types are. If you use calc on integers, you get an integer. If you use it on angles, you get an angle. If you use it on percentages, you get a percentage. All of these are distinct datatypes unrelated to length
. Therefore I don't think it's ever meaningful to explicitly specify what the return type of calc
is since "it's everything calculatable, and you know it when you see it".
I'm afraid I don't understand the article and your explanations. The article doesn't explain what calc is equivalent to in result value (I used "datatype" to mean this).
Is calc(2px)
equivalent to 2px? I assume, yes.
Is calc(2.5px)
equivalent to 2.5px or 3px? The article doesn't say.
What is calc(2.5px + 10pt)
equivalent to? The article doesn't say.
What is calc(100% - 1rem)
equivalent to? The article doesn't say.
As to rounding, the article states:
When calc() is used where an [<integer>](https://developer.mozilla.org/en-US/docs/Web/CSS/integer) is expected, the value will be rounded to the nearest integer. So, calc(1.4) will result in a value of 1. If the fractional part of the value is exactly 0.5, the value will be rounded up. For example, calc(1.5) will result in a value of 2, while calc(-1.5) will round to -1.
As to rounding, the article states:
When calc() is used where an [<integer>](https://developer.mozilla.org/en-US/docs/Web/CSS/integer) is expected, the value will be rounded to the nearest integer. So, calc(1.4) will result in a value of 1. If the fractional part of the value is exactly 0.5, the value will be rounded up. For example, calc(1.5) will result in a value of 2, while calc(-1.5) will round to -1.
That specifically refers to calc
used where an <integer>
is expected. Some CSS properties take integers as values, such as grid-row-start
and z-index
. In these cases, it doesn't make sense to pass a floating point number to them, so the value has to be rounded. These are unitless numbers and have nothing to do with lengths, which we are discussing here.
Is
calc(2px)
equivalent to 2px? I assume, yes.
Yes.
Is
calc(2.5px)
equivalent to 2.5px or 3px? The article doesn't say.
2.5px. It would be truly surprising if it's anything else and I don't know why we would need to specifically point out that "the result of calc
is the result of doing that math".
What is
calc(2.5px + 10pt)
equivalent to? The article doesn't say.
10pt represents a physical length in px. The result is 2.5px + 10pt * [the number of px in a pt].
What is
calc(100% - 1rem)
equivalent to? The article doesn't say.
100%
represents a physical length. The result is 100% * [the length to which percentage values are relative] - 1rem.
All of these examples are calculating based on <length>
. The result is just addition and subtraction of length values. The unit doesn't matter.
calc
is a function overloaded across many data types. calc(1.5 + 1)
and calc(1.5px + 1px)
are two distinct operations that have distinct result types. If it helps, you can even think of them as separate implementations: calcInteger(1.5 + 1)
and calcLength(1.5px + 1px)
. CSS selects the correct implementation for each calc
based on what data type it expects in each context. If you use it in flex: calc(...) calc(...) calc(...)
, then based on the syntax of flex
, which is <number> <number> <length>
(simplified), it would substitute the original with flex: calcNumber(...) calcNumber(...) calcLength(...)
, and then perform each calculation. The only calc
implementation that does rounding is calcInteger
because, well, the result has to be an integer.
I think you have almost converged to the text that needs to be added to the article to make what calc
does clear. The article should describe overloading clearly, and list the separate datatypes.
It should list all integer styles, such as grid-row-start
, and say that calc generates an integer in this case. It should also state that integers cannot be mixed with length
s in the same calc
expression.
Quite a bit of additional text is needed to make the article clear, although it can be orthogonalized by the use of tables. For example, grid-row-start and the other integer styles should be listed in the table.
Your concept that no one needs to know what datatype calc
results in should be explained clearly, because it is confusing as you first stated it. For example, here is my attempt at the explanation:
"Calc
expressions can only appear in style values. Each such style value has its own datatype. The supported datatypes are shown in the following table (...). Calc
expressions can only contain the datatypes appropriate for the style in which they appear, as shown in the table. The result of any calc expression is of that datatype, so, for example, for all calc(grid-row-start + 3px)
is invalid."
I wish I had time to do this, but I'm working on an important website that needs to be released as soon as possible, so my time for writing, checking, and revising is quite limited.
I that that makes sense to be added to the page. We can list all datatypes that are calculable and give examples of each.
I think we have reached agreement. Thanks for the discussion; it has clarified the datatype implications of calc
for me.
Hi @David263. I want to remind you of Mozilla's Community Participation Guidelines (CPG), which ensure that our community remains a welcoming and respectful place for all participants. Being impolite or rude will not be tolerated in any MDN space, including online spaces like this repository. We must communicate with each other in a constructive and considerate manner, especially when we disagree. If you have concerns, let's work together respectfully to address them.
Please be aware that violations of the CPG may result in consequences, including temporary or permanent suspension from participating in discussions or contributing to our projects. You can review the CPG here. Let's keep our conversations aligned with these values so everyone feels comfortable and respected. Thanks for understanding!
I don't think I was rude or abusive in any way or form. First, I stated, "I think we have reached agreement." We had been having a lively discussion about the datatypes of the result of calc
. This discussion was held completely objectively, such that only facts were in discussion, and agreement was finally reached between our two points of view. I was thanking you for the discussion, which is the opposite of being rude. It was being clear and objective.
Second, I stated, "Thanks for the discussion; it has clarified the datatype implications of calc for me." This was neither rude nor abusive, but grateful to you for our discussion.
I'm frankly puzzled how any of my statements here could be considered an abuse of the community standards for contributions, and I'd be grateful if you could reply and explain to me how what I said was rude or abusive. However, if you do not wish to answer this puzzlement, I'm fine.
Finally, I'd like again to gently suggest editing the document to add the clarifications that we discussed. I'm willing to do this myself, if that would be helpful. I would just need instructions on how to make document changes.
I have tried in this and other comments in this thread to be respectful and civil, and again I am puzzled as to how any other interpretation could happen.
I'm happy to share clarification here, David.
My comment was not for anything that happened at the end of the conversation. To be clear, the tone of certain messages in the discussion comes across as frustrated, confrontational, and somewhat condescending. More particularly phrases like "you seem to finally admit," "you don't seem to realize," and "you could have simply agreed from the start," share a sense of irritation and a lack of openness to discussion, which is conveyed through the language. I understand if there is intent on proving a point but we encourage fostering a constructive conversation.
It's important that we communicate with each other in a constructive and considerate manner, even when we disagree. There are no consequences right now because the overall conduct has been fine, but I would not want anyone in the community to have a sour taste while talking to folks in the Mozilla community.
Thank you for providing specific feedback. I now understand your point, and I will try to be more careful of the words I use in the future, especially of not expressing frustration, irritation, confrontation, condescension, or a lack of openness. I will print a sign and keep it next to my computer. Unfortunately, I was raised by parents who did not teach me good social skills, so I have to learn this at age 78. Better late than never.
Again, I hope the article is updated to make the datatype of calc
crystal clear.
I'm willing to do this myself, if that would be helpful. I would just need instructions on how to make document changes.
@David263, we are always eager to have new contributors. There are two ways the document can be changed:
Online on GitHub: It is an easier way to do minor modifications like updating sections, correcting typos etc.
https://github.com/user-attachments/assets/3279df77-ee25-4172-bf56-f3ca91048f24
In some cases, you may need a little understanding of the Markdown language.
From your computer using an IDE (VSCode, Eclipse, IntelliJ IDEA, etc.). This is required to make major changes like complete page revamps and add, move, and delete documents. The initial setup may look big, but it's a one-time thing. To create new documents, you may refer to the page templates.
FWIW you don't even need an IDE - I often use Notepad++. VSCode does make it easier to format according to MDN style and run prettier etc.
@David263 It really is pretty easy to set up. The one thing missing from the guide above though is that the toolchain runs on nodejs/typescript. it is worth installing nvm to manage your node versions because the supported version of node gets updated often enough that you want it to be easy to update.
MDN URL
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
What specific section or headline is this issue about?
Entire document
What information was incorrect, unhelpful, or incomplete?
I visited this page to find out the exact datatype of the result of
calc
. The document states "the expression's result is used as the value for a CSS property", but this is unclear as to the datatype.What did you expect to see?
The document should clearly state that the result of
calc
is a a css integer length in pixels, for example24px
, if this is true.Do you have any supporting links, references, or citations?
I could not find this information in a quick Web search.
Do you have anything more you want to share?
No response
MDN metadata
Page report details
* Folder: `en-us/web/css/calc` * MDN URL: https://developer.mozilla.org/en-US/docs/Web/CSS/calc * GitHub URL: https://github.com/mdn/content/blob/main/files/en-us/web/css/calc/index.md * Last commit: https://github.com/mdn/content/commit/bb48907e64eb4bf60f17efd7d39b46c771d220a0 * Document last modified: 2024-08-13T13:25:16.000Z