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-text] Syntax for percentage-of-width-of-space for 'word-spacing' #3232

Open
fantasai opened this issue Oct 22, 2018 · 27 comments
Open

[css-text] Syntax for percentage-of-width-of-space for 'word-spacing' #3232

fantasai opened this issue Oct 22, 2018 · 27 comments

Comments

@fantasai
Copy link
Collaborator

We just resolved in #2165 to make percentages be relative to the current font size (like ems, but not computing to an absolute length for inheritance). That means we need a different syntax to represent a length proportional to the width of a space (that inherits as a proportion).

@faceless2
Copy link

An "sp" unit? This always struck me as an obvious gap in the font-related units, and it's no different to calculating "ch" or "ic"

@frivoal
Copy link
Collaborator

frivoal commented Dec 3, 2018

An "sp" unit? This always struck me as an obvious gap in the font-related units, and it's no different to calculating "ch" or "ic"

That would inherit as a length, and we're looking for something that inherits as a proportion.

An sp unit isn't inherently wrong, but it is sufficiently close to the ch unit that the demand isn't terribly strong.

@fantasai fantasai removed the css-text-3 Current Work label Dec 4, 2018
@litherum
Copy link
Contributor

litherum commented Feb 2, 2022

A new unit is probably overkill for this. Perhaps just a function would work better?

@fantasai
Copy link
Collaborator Author

fantasai commented Feb 2, 2022

Alternately, just <number> could work. I know Tab hates it, but we're doing the same thing in tab-size also, so it'd be nice to be consistent.

@litherum
Copy link
Contributor

litherum commented Feb 3, 2022

I can't think of a good name for a function, so I think I slightly prefer a raw number.

@tabatkins
Copy link
Member

I'm really against infecting more properties with "<number> as <length>"; it is impossible to calc() with for completely unnecessary technical reasons that authors shouldn't be exposed to.

@litherum
Copy link
Contributor

litherum commented Feb 3, 2022

If there was a function, could you calc inside it?

@tabatkins
Copy link
Member

A function that resolved to a <length> could indeed be used in calc().

@litherum
Copy link
Contributor

litherum commented Feb 3, 2022

It looks like <length>s require units, but this new value represents a ratio or percentage.

How would one represent the concept of "Please set my word spacing to 130% of the space width" in a way that is compatible with calc()?

Would word-spacing: scale-space(calc(100% + 30%)) work?

Or maybe you're suggesting something like word-spacing: calc(scale-space(100% + 30%));?

@tabatkins
Copy link
Member

tabatkins commented Feb 3, 2022

The calc() problem I'm talking about is that, in a calculation, plain numbers need to be scalars: if a property takes a length, it's always valid to multiply the length by a scalar (5px * 3), and never valid to add it to a scalar (5px + 3). But if a number is a non-scalar value (a length), then this becomes impossible to adjudicate. If you start with a word-spacing: 1.3 and decide you need it to be 1px wider, you can't write word-spacing: calc(1.3 + 1px), because that fails to type-check, and there's no reasonable way around that. You need something to indicate that the non-scalar value is a non-scalar - a unit, a percentage sign, a function that we know evaluates to a non-scalar type like <length>, etc.

So yeah, if you wanted to use that last option, then word-spacing: calc(1px + scale-space(130%)) would work, it's just bit verbose.

(I personally think it's completely fine to have more single-use-case units, even or especially ones with longer names to indicate their special-purpose-ness. word-spacing: calc(1px + 1.3spacewidth) seems fine to me, and satisfies my objection from above.)

@litherum
Copy link
Contributor

litherum commented Feb 4, 2022

word-spacing: calc(1px + scale-space(130%)) and word-spacing: scale-space(130%) seem fine to me.

@frivoal
Copy link
Collaborator

frivoal commented Feb 4, 2022

I'm not too sure why a function is preferable to a unit. Can you explain?

@tabatkins
Copy link
Member

From Myles' earlier comment:

A new unit is probably overkill for this. Perhaps just a function would work better?

@litherum
Copy link
Contributor

litherum commented Feb 4, 2022

When I said "overkill" I meant "I see no use case for this outside the property in question, so let's scope the feature accordingly."

@fantasai
Copy link
Collaborator Author

fantasai commented Feb 15, 2022

@litherum Well, there's tab-size also, so we have at least two properties that need this syntax.

tab-size is currently using bare numbers. I understand Tab's point about how this is bad, but at least it's consistent. Consistently solving the problem for both properties would also be nice, though. I just don't want us to do one thing here and something else in tab-size.

@fantasai
Copy link
Collaborator Author

fantasai commented Feb 15, 2022

Also, as @frivoal mentioned, this needs to inherit as itself and not as a <length> or a <percentage>, so it's not something that can be folded into the existing <length-percentage> structure. We'd need something like <length-percentage-ratio> in order to combine it with lengths.

@fantasai
Copy link
Collaborator Author

fantasai commented Feb 15, 2022

I think we have a few options here:

  • Just use <number>
  • Reuse fr units, define mathematical combinations with <length-percentage> to be allowed in this property.
  • Mint a new unit, e.g. pr or whatever, define <length-percentage-proportion> or whatever
  • Define a function like space(<number>) which inherits as itself and can be used inside calc() along with length-percentage.

If we're taking any of the new syntax options, we might consider also allowing bare <number> to work so that tab-size and word-spacing can share the same syntactic space for the same operation.

Please note that while in tab-size this always refers to the space character, in word-spacing it can apply to a variety of different characters, and is applied as a multipler per character. In other words, even its used value is not a singular length value that can be applied to the whole element.

@tabatkins
Copy link
Member

Yes, tab-size is currently a number. It's terrible, and I'm going to push very strongly against spreading this precedent any further. It's currently contained to exactly two properties and I don't want it going any further when there's no reason for it. In other words, the goodness of (very vague) precedent is overwhelmed by the practical badness of it.

It is absolutely bad to have a length-ish value that can't be combined with other length-ish values. If vague precedent is the only reason for doing this I'm going to strongly object to it.

Please note that while in tab-size this always refers to the space character, in word-spacing it can apply to a variety of different characters, and is applied as a multipler per character. In other words, even its used value is not a singular length value that can be applied to the whole element.

So this means that the precedent of tab-size is even less applicable.

Mint a new unit, e.g. pr or whatever, define <length-percentage-proportion> or whatever

No need for this, we can still call it a <length>, because it is. It just resolves at a different time; we already have lengths that resolve at multiple different times, so this isn't anything special in that regard, and the fact that it has to resolve at actual value time is just a new wrinkle, not a fundamental difference.

The unit would just be context-sensitive, and probably, uh, resolve to 0 in any other property I guess? Or perhaps resolve relative to ch.

@fantasai
Copy link
Collaborator Author

fantasai commented Mar 11, 2022

we already have lengths that resolve at multiple different times

No we don't. They all compute to an absolute length. All lengths compute to each other, that's what makes them the same fundamental type.

@tabatkins
Copy link
Member

No, length-percentages don't becomes lengths until used value time. When a value can be converted to its canonical unit isn't part of the definition of a type.

Once again, my argument is that making a <length> that cannot be used in calc() with other length units is a mistake that we should not propagate beyond the two places it currently occurs. The two usages of this pattern don't form a popular well-known usage pattern that authors can extrapolate from, so precedent is weak to nil.

@fantasai
Copy link
Collaborator Author

<length-percentage> and <length> are two different types, Tab. My point is, whatever this new thing this is, it's cannot be part of <length>.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-text] Syntax for percentage-of-width-of-space for 'word-spacing', and agreed to the following:

  • RESOLVED (for now): ‘word-spacing’ takes a number value
The full IRC log of that discussion <emeyer> Topic: [css-text] Syntax for percentage-of-width-of-space for 'word-spacing'
<emeyer> github: https://github.com//issues/3232
<fantasai_> https://github.com//issues/3232#issuecomment-1040836766
<emeyer> fantasai: We’ve been wanting to represent percentage spacing in word-spacing as a percentge of the character’s advance width.
<TabAtkins> we want the ability to say "words should be separated by two spaces worth of whitespace", for example
<emeyer> …We’re already using percentages against font size.
<emeyer> …we already have a meaning for all the lengths, and em for percentages. Still want “increase width of this word separator character by X%”.
<emeyer> …Space is the most commn word separator, but there are others with different advance widths.
<emeyer> …We want to represent a multiplier, not a percentage or length.
<emeyer> …I think we have some number of options. One: use a number. Cons: you can’t combine numbers and lengths in calc()s.
<emeyer> Two: Use a different unit, like ‘fr’. We could mint a new unit, either a generic one or one specific to this property.
<emeyer> Three: We could mint a new function.
<emeyer> TabAtkins: The fact that this can have different effects on per-character basis makes it more strongly not a length. My objections in the issue are largely irrelevant; fine with it being a number.
<emeyer> astearns: It’s a number that inherits as itself.
<emeyer> florian: Do we expect people to actually calc() this sort of thing?
<emeyer> fantasai: I don’t know.
<astearns> s/It's a number/It's a unit/
<emeyer> TabAtkins: In the general case, no, but it might be sense to double ASCII space a tweak it. I don’t think so, but…?
<astearns> ack dbaron
<emeyer> dbaron: This is a sort of general problem that we should find a decent solution for that isn’t a horrible hack. We keep running into situations where we want a value that’s relative to something computed for inheritance purposes. Maybe we need to actually figure out a more permanent solution for this.
<emeyer> fantasai: We have percentages usually, but we’re alreaday using them here.
<aja> q+
<emeyer> dbaron: Part of what I mean is that for lengths, we have different units. We might want different relative units. Maybe ‘fr’ was going down the right path. We should have a solution we can re-use multiple times.
<emeyer> fantasai: If the ‘x’ unit was available, that might be nice.
<emeyer> florian: If you know of it, it does the job find, but discovering is a mess.
<florian> s/of it/of the fr unit/
<emeyer> astearns: I agree this is a problem that crops up in several places and we have one relief valve, where we use a number and set that number to have a special relationship.
<emeyer> fantasai: Two relief valves: percentages and numbers. The problem with numbers is you can combine with calc().
<emeyer> s/can combine/can’t combine/
<emeyer> florian: We don’t need a unit system for percentages, we only ever need two at most.
<emeyer> fantasai: Maybe we need a generic “this is a number” unit for calc()
<emeyer> florian: I thikn dbaron said this is a problem in a number of places. What number of places? If it’s a few, maybve that’s okay. If it’s a lot, maybe ‘fr’ is the way to go because that’s learnable.
<emeyer> s/thikn/think/
<emeyer> fantasai: border-image uses both, I think.
<astearns> percentage(150%, font-size)
<emeyer> dbaron: I think there are a bunch of cases where percentage confuses people because they don’t always know what it means.
<fantasai_> also line-height, but that was a terrible mistake imho
<emeyer> florian: I retract my earlier comment about two types of percentages, we do have more.
<iank_> (even on single properties percentages can resolve to different things depending on the context, e.g. top :P )
<dbaron> dbaron: ... sometimes % of height, % of width, % of font-size
<TabAtkins> 5%(em)
<fantasai_> https://www.w3.org/TR/css-backgrounds/#border-image-width
<emeyer> astearns: Spelling out percentages in functoinal form would be easier than some abbreviation.
<emeyer> florian: Maybe you could do “2% height + 2% width” in some way.
<florian> s/2% height + 2% width/2%(height) + 2%(width)/
<emeyer> iank_: We want to be very careful if we’re introducing percentages that can resolve against specific things. Cyclic dependencies are a risk.
<TabAtkins> %(foo) is just a new unit, it's not currently allowed by Syntax
<iank_> I see.
<emeyer> astearns: We could restrict where those identifiers could be used to avoid cycles.
<TabAtkins> 5foo% vs 5%(foo) vs just 5foop
<emeyer> fantasai: That feels excessively complicated for what weære dealing with here.
<emeyer> dbaron: Maybe we should make more things like ‘fr’ rather than re-using it all the time. Doing that seems the least horrible.
<emeyer> astearns: We could resolve to use a unit, but we lack consensus on what that should be named.
<emeyer> fantasai: I number either a new unit, or just use numbers.
<emeyer> s/I number/I think/
<dbaron> iank_: new unit that's only valid for word-spacing?
<dbaron> fantasai_: yes, or maybe also tab-size
<emeyer> fantasai: It would be nice if there was syntactic compability.
<aja> 1) would % of 'ch' unit be appropriate? 2) consistency with letter-spacing would be a plus for authors.
<emeyer> florian: Bikeshedding aside, that sounds reasonable unless dbaron is right and we’ll need a whole bunch of new units that are conceptually similar.
<fantasai_> 1) no, because it resolves to an absolute length 2) no use case, but could in theory (generally people don't want inconsistent tracking)
<emeyer> …If we think we need a bunch, we do that but try to come up with a scheme that lets us group these.
<dbaron> Also, vh, vw, etc., etc., are very %-like (but the user can't tell which way they inherit).
<emeyer> astearns: I’m not hearing moving toward resolution aside from not being interested in making a length.
<emeyer> fantasai: I propose we use a number for now. If we come up with a good unit we want later, we could make this as ‘tab-size’ accept it.
<emeyer> s/this as/this and/
<emeyer> astearns: Anyone with concerns with resolving that ‘word-spacing’ takes a number and punting on general solution until a later date?
<dbaron> I'm not objecting, but it does feel like just postponing the problem...
<emeyer> RESOLVED (for now): ‘word-spacing’ takes a number value
@karip
Copy link

karip commented Apr 14, 2022

You may want to consider how allowing word-spacing to take a number value affects SVG.

SVG1.1 defines word-spacing so that it can accept numbers: "For SVG, if a <length> is provided without a unit identifier (e.g., an unqualified number such as 128), the SVG user agent processes the <length> as a width value in the current user coordinate system."

SVG2 redefines the property so that it doesn't allow lengths without a unit identifier. However, presentation attributes still replace instances of <length> in grammar with [<length> | <number>].

Safari, Firefox and Chrome support word-spacing without a unit as a presentation attribute. Safari and Chrome also support it as a style property. Here's a JSFiddle example.

@tabatkins
Copy link
Member

Ah shoot, and word-spacing is on the list of properties that allow <quirky-length>, too: https://drafts.csswg.org/css-values/#deprecated-quirky-length

Agenda+ to reverse the resolution and just define a unit, then.

@fantasai
Copy link
Collaborator Author

Can we use x? Then anywhere we need a multiplier we can use e.g. 2x and that would be reasonably readable.

(The main impediment to this being that certain people decided to alias x to dppx ...)

@tabatkins
Copy link
Member

Right, x is already claimed as a <resolution>, so we can't use it.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed percentage-of-width-of-space, and agreed to the following:

  • RESOLVED: Reverse previous resolution. Add a unit instead, name tbd
The full IRC log of that discussion <emilio> topic: percentage-of-width-of-space
<emilio> github: https://github.com//issues/3232
<emilio> TabAtkins: last week we agreed to go ahead and accept that the new unit can just be a number
<emilio> ... it was since pointed out that in svg word-spacing is defined and SVG allows all length properties to be specified as number
<emilio> ... which maps to pixel
<emilio> ... after that I realized that word-spacing accepts quirky lengths
<emilio> ... so `word-spacing: 2` maps to pixels
<emilio> ... given we were not super-happy with numbers I propose to reverse the resolution
<emilio> ... and resolve that we will give it a unit name
<emilio> q+
<TabAtkins> emilio: we may be able to get away with numbers if we say that they mean spaces in non-quirks mode
<TabAtkins> emilio: All major browser engines map SVG attribute numbers to pixels at parse time
<TabAtkins> emilio: You can parse numbers at quirks mode and still have a specified value px
<TabAtkins> Rossen_: Then you'll have a type difference which is weird
<TabAtkins> emilio: If you get css text between a quirks and non-quirks stylesheet it can be confusing, but otherwise this is already an issue
<TabAtkins> emilio: Not opposed to a unit, just pointing out that it *is* possible
<Rossen_> ack emilio
<emilio> RESOLVED: Reverse previous resolution. Add a unit instead, name tbd
<fantasai> ScribeNick: fantasai
@fantasai fantasai added the Agenda+ Later Lower-priority items that are flagged for CSSWG discussion label Dec 30, 2022
@astearns astearns removed the Agenda+ Later Lower-priority items that are flagged for CSSWG discussion label Sep 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment