Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-syntax] numeric separators #9293

Closed
romainmenke opened this issue Sep 1, 2023 · 12 comments
Closed

[css-syntax] numeric separators #9293

romainmenke opened this issue Sep 1, 2023 · 12 comments

Comments

@romainmenke
Copy link
Member

romainmenke commented Sep 1, 2023

In JavaScript you can use underscores as numeric separators.
This is purely syntax sugar.

From : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#numeric_separators

To improve readability for numeric literals, underscores (_, U+005F) can be used as separators:

1_000_000_000_000
1_050.95
0b1010_0001_1000_0101
0o2_2_5_6
0xA0_B0_C0
1_000_000_000_000_000_000_000n

https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-NumericLiteralSeparator

CSS number tokens and JS number tokens are mostly the same.
This makes it easy to copy/paste values between the two languages.

It would be nice if CSS also has support for numeric separators, for the same reasons as why they were added to JavaScript and to make it easier to copy/paste from JavaScript to CSS.


As far as I can tell these sequences do not form useful tokens in todays syntax.

1_000_000_000_000 is a dimension token with a value of 1 and a unit of _000_000_000_000.

@tabatkins
Copy link
Member

tabatkins commented Sep 1, 2023

Right, they're currently parsed as dimension tokens. I think there is some use of _ prefixes in browser-internal units; I seem to recall a __qem unit or something to handle a length quirk at some point. But I'm pretty sure they're all something non-digit following the underscore.

So the JS rules are that _ isn't allowed at the beginning or end of the number, and you can't have two in a row - _1, 1_, and 1__0 are all invalid. Matching that in CSS parsing is pretty convenient, then - if we see an underscore, we just check if the next character is a digit or not, and decide whether to keep parsing a number or switch to parsing the unit.

So yeah, this is likely safe?

So, specifically, we'd change steps 3, 4.2, and 5.3 of https://drafts.csswg.org/css-syntax/#consume-a-number to skip past single underscores followed by a digit, as long as we'd already seen at least one digit.

@romainmenke
Copy link
Member Author

romainmenke commented Sep 1, 2023

Yes, although step 3, not 2?


Haven't tested this through but this seems fairly straight forward : https://github.com/csstools/postcss-plugins/pull/1099/files

It does make things a bit messier and there will be more lookahead:

  • current code point is a digit
  • current + 1 is a low line
  • current + 2 is also a digit

-> advance 3 code points.

whereas the current algorithm doesn't do any lookahead as long as the current codepoint is a digit.

@tabatkins
Copy link
Member

Yeah, a little more lookahead, but still within our current budget of 3 characters.

Yes, although step 3, not 2?

Yup, fixed. (And clarified step 4.2.)

@Crissov
Copy link
Contributor

Crissov commented Sep 5, 2023

0b…, 0o…, 0x… and …n from the quoted JS justification for a group divider are not relevant number syntaxes in CSS, except if this core change would mean that sRGB colors could and would also be written as #1_2_3, #1_2_3_F, #11_22_33, #11_22_33_FF.

If long runs of decimal digits were an issue in CSS, I’d expect this to be fixed by introducing a new, better suited unit, which is a concept JS does not have (yet). The entire use case seems to be ”JS syntax compatibility for copy-pasting bare numbers“, when bare numbers are hardly used in CSS and a lot of JS’s number formats are not supported in CSS.

Just to be clear, digit grouping is a good thing per se, I’m just not convinced that making breaking changes to the core grammar is sufficiently justified by ”JS has this“, especially since other, non-breaking changes with the same underlying intention (i.e. more units, e.g. #309) have regularly been rejected.

@romainmenke
Copy link
Member Author

romainmenke commented Sep 5, 2023

0b…, 0o…, 0x… and …n from the quoted JS justification for a group divider are not relevant number syntaxes in CSS,

This was quoted directly from the MDN docs page for the JS numeric separators.
I've updated the formatting to make it more clear that this is a direct quote.

This proposal is only for _ as a separator between digits as those digits exist in the CSS syntax today.

I’m just not convinced that making breaking changes to the core grammar is sufficiently justified by ”JS has this“

My current assumption is that this is non-breaking in practice.
If it turns out to be breaking I would agree that it is not worth it.

@Loirooriol
Copy link
Contributor

I'm not convinced this would be useful in CSS. The only case where I have seen big numbers is z-index: 9999999999999 and then the author doesn't really care about the exact number of digits, they just want something big.

@plinss
Copy link
Member

plinss commented Sep 6, 2023

Probably more useful after the decimal point when using fractions that have lots of significant digits

@Loirooriol
Copy link
Contributor

But browsers use layout units of 1/60 or 1/64 pixels, and CSSOM has a limit of 6 decimals. So I haven't seen authors using lots of decimal digits.

@romainmenke
Copy link
Member Author

Delays in JavaScript are in milliseconds and they can be fairly large numbers.
In CSS there is the s unit, but then you lose copy/paste between the two.

Durations/delays were the main example I had in mind when submitting this.

Dimensions with a rem unit often seem to have larger numbers of digits.
It's questionable if adding a separator would make those more readable...


Some samples from real CSS I have access to :

animation: MAP_LOADING_ANIMATION 1.4925373134328357s cubic-bezier(0, 0.2, 0.8, 1) infinite;
animation-delay: -0.7462686567164178s;
line-height: 1.307692307;
padding-top: 237.037037%;
height: calc(4em * 1.57142857);
padding-bottom: 68.115942%;
letter-spacing: 0.046875rem;
height: 117.1875px;
padding-top: 117.1875%;
letter-spacing: 0.046875rem;
letter-spacing: 0.038125rem;
letter-spacing: 0.054375rem;
letter-spacing: 0.038125rem;
letter-spacing: 0.114375rem;
letter-spacing: 0.163125rem;
letter-spacing: 0.070625rem;
letter-spacing: 0.054375rem;
letter-spacing: 0.040625rem;
max-width: 48.4375rem;
max-width: 30.9375rem;
width: calc(100% - 10.6875rem);
max-width: 59.8125rem;
width: 10.9375rem;
width: 14.1875rem;
width: 10.9375rem;
padding-bottom: 42.8571%;
padding: 0.59375rem 1.25rem;
letter-spacing: 0.03375rem;
letter-spacing: 0.03625rem;
letter-spacing: 0.03125rem;
grid-template-columns: repeat(auto-fill, 10.6875rem);
min-width: 10.6875rem;
width: 10.6875rem;
max-width: 23.4375rem;
width: 10.3125rem;
max-width: 20.9375rem;
max-width: 26.0625rem;
letter-spacing: 0.03125rem;
--width-mobile-nav-xsmall: 19.6875rem;
top: 66.6667vw;
letter-spacing: -0.03125rem;
width: 14.3125rem;
width: 11.5625rem;
letter-spacing: 0.04375rem;
letter-spacing: -0.03125rem;
letter-spacing: -0.09375rem;
letter-spacing: 0.02125rem;
letter-spacing: -0.03125rem;
letter-spacing: -0.09375rem;
letter-spacing: 0.04375rem;
letter-spacing: 0.05625rem;
letter-spacing: 0.03375rem;
letter-spacing: 0.02625rem;
padding: 0.78125rem 3.125rem;
margin-bottom: 2.15625rem;
padding-bottom: 10.3125rem;
margin-bottom: 3.45625rem;
margin-bottom: 2.45625rem;
padding: 0.78125rem 3.125rem;
margin-top: 0.78125rem;
width: 27.3125rem;
padding-top: 1.15625rem;
margin-bottom: 13.3125rem;
bottom: calc(0.90625rem + 1.6875rem);
padding-top: 1.71875rem;
padding-bottom: 2.03125rem;
padding-top: 1.90625rem;
padding-top: 23.0625rem;
margin-top: 10.9375rem;
margin-bottom: 10.9375rem;
grid-template-columns: 28.25rem 32.6875rem;
padding-top: 12.8125rem;
min-height: 10.9375rem;
min-height: 13.4375rem;
top: calc(50% - 0.03125rem);
grid-auto-rows: calc(72.1875vw + 3.125rem);
min-height: calc(72.1875vw + 3.125rem);
top: calc(50% - 0.03125rem);
grid-auto-rows: calc(72.1875vw + 3.125rem);
min-height: calc(72.1875vw + 3.125rem);
top: calc(50% - 0.03125rem);
grid-auto-rows: calc(72.1875vw + 3.125rem);
min-height: calc(72.1875vw + 3.125rem);
min-width: 11.5625rem;

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-syntax] numeric separators, and agreed to the following:

  • RESOLVED: Don't add to CSS right now due to lack of use cases/user voices to add it
The full IRC log of that discussion <dael> TabAtkins: Raised the topic that JS allows _ for numeric separators for numeric literals. If you have a large number with many digits it's hard to read. Suggestion is add them to CSS syntax as wel
<Rossen_> q?
<iank_> we can also change those units
<dael> TabAtkins: I think this is safe to do. 1_000 is a dimension with value 1. We have a few places with _ prefix but it's not followed by digits. It's internal stuff.
<dael> TabAtkins: Arguments against is not very valuable. Large and small numbers show up a lot in JS and precision is important. Much less the case in CSS. large numbers the important thing is they're big. Being able to tell a 6 vs 7 digit number apart for your page isn't common in practice.
<dael> TabAtkins: Same with decimals. Pixels are limited to 1/64th or 1/60th. Much less than JS precision.
<iank_> +1 to no change - doesn't seem super valuable.
<astearns> +1 to no change
<dael> TabAtkins: Basic argument against is we just don't need it. I'm inclined to go no change due to low need. But I think it's safe if someone wants to have it and I'm happy to make the change
<smfr_> +1 to no change
<iank_> (unless strong desire from community)
<fantasai> +1 TO tAB'S ANALYSIS
<dael> Rossen_: Proposal is raise awareness but don't add to CSS right now due to lack of use cases/user voices to add it
<emeyer> +1 to no change (the only time I’ve ever seen long numbers is in z-index and precision wasn’t needed)
<dael> Rossen_: Obj to resolving no change?
<dael> RESOLVED: Don't add to CSS right now due to lack of use cases/user voices to add it
<fantasai> s/TO tAB'S ANALYSIS/to Tab's analysis/

@tabatkins
Copy link
Member

Per WG resolution, closing this as no change; the use-cases for large and small numbers in JS don't generally apply to CSS, which largely only needs values in a fairly small number of digits. People certainly write numbers with longer values (probably copied from a calculation done in JS or other language using doubles), but the exact value past the first few digits is rarely important.

We're open to changing this if we get compelling, realistic use-cases where numbers with large numbers of digits (more than 6 on either side of the decimal point) are important to be able to distinguish fairly precisely.

@romainmenke
Copy link
Member Author

Agreed, thank you for considering this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants