You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-text] Allow letter-spacing to have unitless values like line-height #2165
There is often a need to set the letter spacing of an element to a fraction of its font size to reproduce a given design, and have it propagate down as it should (like most text-related properties, letter-spacing is inherited). That can be done with an em value, but unfortunately it breaks when the font size changes in a descendant element, because the value is computed using the font-size that is used where the letter-spacing is set.
In this example, we want the letter spacing to be 0.1 times the font size. This is the equivalent of setting the "tracking" in Photoshop to 100 since "Tracking and kerning are both measured in 1/1000 em" (source: https://helpx.adobe.com/photoshop/using/line-character-spacing.html). However, that value is computed directly in .rich-text and becomes a fixed 1.6px, so in an h1, even though we set the font-size to 32px, the letter spacing is still 1.6px and not 3.2px like we'd expect. We have to duplicate the letter-spacing: 0.1em; rule every time we change the font size in a descendant to have the result we want.
Proposed solution
Introduce a new unitless value option for letter-spacing that works like line-height's unitless values. Notice in the example above, the line height is set to 1.5 times the font size, and it properly propagates down to h1 and any other descendant that changes the font size. I believe a unitless value for letter-spacing should work exactly like that. We would simply have to remove the em in the example above and it would work.
Hi @benface, this seems like one of the problems that CSS Variables were designed to solve for us—passing down values from a parent to its children! I'd rather embrace a solution that uses CSS features available today (using CSS Variables to their fullest) rather than expanding CSS to include new units to accomplish something that's already possible.
In this particular case of "passing down a value from a parent to its children" you want a new unit to set letter-spacing but how many other use-cases of the same "passing down a value from a parent to its children" technique that CSS Variables currently support would adding this new 'letter-spacing' unit help? Probably not that many other use cases.
So, phrased another way: How many new units would you need to add to CSS if we want to avoid using CSS Variables cases where we want to pass a value down to children?
Makes sense @tomhodgins, but I would add two things:
I'm not proposing a new unit per se; unitless values are allowed in lots of places across CSS.
A huge part of what bothers me about this is that it's inconsistent. I feel like line-height and letter-spacing are very closely related, they are basically leading and tracking for CSS, vertical and horizontal spacing. It annoys me that I cannot use the same units between the two properties.
Note: unitless values are a new unit - they're just a lazier way of adding a new unit without actually minting a new suffix. I'm trying to avoid adding new ones in new designs, when possible - when plain numbers are actually lengths in disguise, it makes calc() dramatically more complicated. (See the third note in https://drafts.csswg.org/css-values/#calc-syntax where we talk about how it's not actually allowed - you can't add together line-height: 1 and line-height: 20px into a line-height: calc(1 + 20px) - we'd need to mint an actual unit for that to work.)
Reacted by Benoît Rouleau, Nadya678, Masataka Yakura, Keith J. Grant, Christoph Päper, Bjørn Hoffmann and Mark Fisher
I was thinking about this problem just the other day, and was surprised this wasn't a solved problem already. Totally agree with the premise.
@tabatkins We could use percents here. It's inconsistent with how line-height works, but imho line-height's use of percents is broken; we don't resolve them anywhere else.
An interesting question is whether the ratio should be relative to em or ch; imho we should go with em which is more fundamental, and once we have unit math calc() can be used to provide the other ratios.
So the proposal is that letter-spacing accept percentages, which inherit as percentages, with 100% = 1em on the current element.
Then there's the question of what word-spacing should do. Currently a percentage on word-spacing multiplies the width of the affected word separator character (typically a space, but some scripts use a visible glyph, Ethiopic being the main one with contemporary use). Should we keep that definition or make it match word-spacing?
Then there's the question of what word-spacing should do.
BTW. Why word-spacing:0px still make a gap between words? Is there solution to set no spacing between words and between inline-blocks without removing CR LF from code?
@fantasai, I believe that calculating percentage from the width of the normal inter-word space is useful (one quite common use case would be removing spaces completely with word-spacing: -100%, some designs could require doubling the spaces with 100% value, etc.). I'd say that letter-spacing values relative to the inter-word space width (e.g. spacing the letters for a half of it) also would have its use cases (Photoshop is not the only design tool, after all, designing directly in browser is also quite popular), so if font-related percentages would be redefined, it would be worth reintroduce this measure as a new unit (maybe ws?) suitable for both properties, as well as for margins/paddings etc.
And what about reusing the fr unit for font-related properties? It's already a "length-but-not-exactly", it means "fraction", so it could inherit as a fraction of the font-size instead of the computed length... Is it a too crazy idea?
@Nadya678, the word-spacing property is defined as an "extra spacing in addition to the intrinsic inter-word spacing". The currently proposed (yet not supported by browsers) standard CSS way to shrink inter-word spaces to zero is word-spacing: -100%. The most common practical CSS solutions are either setting font-size: 0 to the container and resetting it for the items, or setting the word-spacing to some negative value like -0.31em (the exact value depends on the white-space character width, usually between 0.25 and 0.4em). For monospace fonts, word-spacing: -1ch should work. Another option is to use a custom font where the whitespace character has zero width (like this). However, the best way to avoid unwanted spaces between design blocks is not using inline-blocks for them at all and using Flexbox instead.
I thing the word-spacing: -100% or word-spacing: none is good solution for it. I know about hacks for it but I like use CSS without modyfing HTML (additional blocks, or the > closest the <, but the code is less clear to read).
BTW. The flex-box has side effects and It cannot be used in part of layouts. Also hacks has side efects like losing of antialiasing on iOS browsers (font-size:0).
doubling the spaces
Yes - for part of standard fonts it is very appreciated.
And what about reusing the fr unit for font-related properties?
How will it work? How to use the pseudo-unit for spacing?
The Working Group just discussed font-relative letter-spacing, and agreed to the following resolutions:
RESOLVED: defer this to text L4
The full IRC log of that discussion
<fantasai> Topic: font-relative letter-spacing
<fantasai> https://drafts.csswg.org/css-text-3/issues-lc-2013#issue-167
<dael> github: https://github.com//issues/2165
<emilio> rune_: btw, Blink does fail the tests in https://github.com/web-platform-tests/wpt/pull/10422 for elements not in the flattened tree, at least on release.
<dael> fantasai: This was a feature request. Worth a quick look. Might have to go in L4 unless someone has a quick solution.
<xidorn> (dbaron: on, I see, yes, we enabled that in nightly)
<dael> fantasai: We can add unitless values or add % or add a united value.
<dael> florian: TabAtkins doesn't like unitless values
<dael> fantasai: word spacing the % means that character's own width.
<dael> fremy: I understand what we're doing In previous issue with cr we render because it's a control character. We render the black square.
<dael> florian: For letter spacing I feel confortable defer
<dael> astearns: Obj to defer this to text L4
<dael> RESOLVED: defer this to text L4
Not sure how I feel about this... the inconsistency is regrettable, but the proposed behavior here (inheriting as a percentage and resolving "late") is more useful than computing to a <length> and inheriting that, and expressing the value as a percentage seems better than a unitless number.
The behavior of line-height: <percentage> seems more like an unfortunate (but no doubt unchangeable) legacy misfeature than a desirable feature; it would be sad if it forever blocks us from using percentage values in a more useful way in new properties.
All layout-relative percentages are inherited as percentages. The problem is that I'm not sure any of them inherit by default, so you'd only see the effect if you were explicitly using the inherit value, which is quite rare.
This is probably close to a category feature: the only reason to resolve post-computed value is if you depend on layout, or have a special reason to want your resolution-reference to change as you inherit; (almost?) all of the former are non-inherited layout-related properties, while the latter is rare (like currentcolor).
All layout-relative percentages are inherited as percentages. The problem is that I'm not sure any of them inherit by default, so you'd only see the effect if you were explicitly using the inherit value, which is quite rare.
Yes, sorry, I meant for inherited properties. I could only think of font-size which behaves like line-height.
Looking back, I see that @fantasai explicitly mentioned the inconsistency with line-height back in #2165 (comment) (the original suggestion to use percentages).
Personally, I agree with the assessment that "line-height's use of percents is broken", and I don't think we should let that stand in the way of using percent more appropriately here.
Reacted by Benoît Rouleau, Ilya Streltsyn and fantasai
Activity
tomhodgins commentedon Jan 4, 2018
Hi @benface, this seems like one of the problems that CSS Variables were designed to solve for us—passing down values from a parent to its children! I'd rather embrace a solution that uses CSS features available today (using CSS Variables to their fullest) rather than expanding CSS to include new units to accomplish something that's already possible.
In this particular case of "passing down a value from a parent to its children" you want a new unit to set
letter-spacingbut how many other use-cases of the same "passing down a value from a parent to its children" technique that CSS Variables currently support would adding this new 'letter-spacing' unit help? Probably not that many other use cases.So, phrased another way: How many new units would you need to add to CSS if we want to avoid using CSS Variables cases where we want to pass a value down to children?
benface commentedon Jan 4, 2018
Makes sense @tomhodgins, but I would add two things:
line-heightandletter-spacingare very closely related, they are basically leading and tracking for CSS, vertical and horizontal spacing. It annoys me that I cannot use the same units between the two properties.tabatkins commentedon Jan 4, 2018
Note: unitless values are a new unit - they're just a lazier way of adding a new unit without actually minting a new suffix. I'm trying to avoid adding new ones in new designs, when possible - when plain numbers are actually lengths in disguise, it makes calc() dramatically more complicated. (See the third note in https://drafts.csswg.org/css-values/#calc-syntax where we talk about how it's not actually allowed - you can't add together
line-height: 1andline-height: 20pxinto aline-height: calc(1 + 20px)- we'd need to mint an actual unit for that to work.)fantasai commentedon Jan 5, 2018
I was thinking about this problem just the other day, and was surprised this wasn't a solved problem already. Totally agree with the premise.
@tabatkins We could use percents here. It's inconsistent with how
line-heightworks, but imholine-height's use of percents is broken; we don't resolve them anywhere else.An interesting question is whether the ratio should be relative to
emorch; imho we should go withemwhich is more fundamental, and once we have unit mathcalc()can be used to provide the other ratios.So the proposal is that
letter-spacingaccept percentages, which inherit as percentages, with100%=1emon the current element.Then there's the question of what
word-spacingshould do. Currently a percentage onword-spacingmultiplies the width of the affected word separator character (typically a space, but some scripts use a visible glyph, Ethiopic being the main one with contemporary use). Should we keep that definition or make it matchword-spacing?Nadya678 commentedon Jan 7, 2018
BTW. Why word-spacing:0px still make a gap between words? Is there solution to set no spacing between words and between inline-blocks without removing CR LF from code?
SelenIT commentedon Jan 8, 2018
@fantasai, I believe that calculating percentage from the width of the normal inter-word space is useful (one quite common use case would be removing spaces completely with
word-spacing: -100%, some designs could require doubling the spaces with100%value, etc.). I'd say thatletter-spacingvalues relative to the inter-word space width (e.g. spacing the letters for a half of it) also would have its use cases (Photoshop is not the only design tool, after all, designing directly in browser is also quite popular), so if font-related percentages would be redefined, it would be worth reintroduce this measure as a new unit (maybews?) suitable for both properties, as well as for margins/paddings etc.And what about reusing the
frunit for font-related properties? It's already a "length-but-not-exactly", it means "fraction", so it could inherit as a fraction of the font-size instead of the computed length... Is it a too crazy idea?@Nadya678, the
word-spacingproperty is defined as an "extra spacing in addition to the intrinsic inter-word spacing". The currently proposed (yet not supported by browsers) standard CSS way to shrink inter-word spaces to zero isword-spacing: -100%. The most common practical CSS solutions are either settingfont-size: 0to the container and resetting it for the items, or setting theword-spacingto some negative value like-0.31em(the exact value depends on the white-space character width, usually between 0.25 and 0.4em). For monospace fonts,word-spacing: -1chshould work. Another option is to use a custom font where the whitespace character has zero width (like this). However, the best way to avoid unwanted spaces between design blocks is not using inline-blocks for them at all and using Flexbox instead.Nadya678 commentedon Jan 8, 2018
I thing the
word-spacing: -100%orword-spacing: noneis good solution for it. I know about hacks for it but I like use CSS without modyfing HTML (additional blocks, or the>closest the<, but the code is less clear to read).BTW. The flex-box has side effects and It cannot be used in part of layouts. Also hacks has side efects like losing of antialiasing on iOS browsers (font-size:0).
Yes - for part of standard fonts it is very appreciated.
How will it work? How to use the pseudo-unit for spacing?
css-meeting-bot commentedon Apr 11, 2018
The Working Group just discussed
font-relative letter-spacing, and agreed to the following resolutions:RESOLVED: defer this to text L4The full IRC log of that discussion
<fantasai> Topic: font-relative letter-spacing<fantasai> https://drafts.csswg.org/css-text-3/issues-lc-2013#issue-167
<dael> github: https://github.com//issues/2165
<emilio> rune_: btw, Blink does fail the tests in https://github.com/web-platform-tests/wpt/pull/10422 for elements not in the flattened tree, at least on release.
<dael> fantasai: This was a feature request. Worth a quick look. Might have to go in L4 unless someone has a quick solution.
<xidorn> (dbaron: on, I see, yes, we enabled that in nightly)
<dael> fantasai: We can add unitless values or add % or add a united value.
<dael> florian: TabAtkins doesn't like unitless values
<dael> fantasai: word spacing the % means that character's own width.
<dael> fremy: I understand what we're doing In previous issue with cr we render because it's a control character. We render the black square.
<dael> florian: For letter spacing I feel confortable defer
<dael> astearns: Obj to defer this to text L4
<dael> RESOLVED: defer this to text L4
fantasai commentedon Sep 16, 2018
@litherum points out in #3118 that we also have this problem with
text-underline-offset.19 remaining items
emilio commentedon Jan 7, 2020
To be clear,
line-height: <percentage>computes to a<length>in all browsers:Shows
16px, not32px.jfkthame commentedon Jan 7, 2020
Not sure how I feel about this... the inconsistency is regrettable, but the proposed behavior here (inheriting as a percentage and resolving "late") is more useful than computing to a
<length>and inheriting that, and expressing the value as a percentage seems better than a unitless number.The behavior of
line-height: <percentage>seems more like an unfortunate (but no doubt unchangeable) legacy misfeature than a desirable feature; it would be sad if it forever blocks us from using percentage values in a more useful way in new properties.benface commentedon Jan 7, 2020
But are there properties where a percentage value is inherited as a percentage? I can't think of any.
jfkthame commentedon Jan 7, 2020
I think that's how
background-position-{x,y}works, for example?tabatkins commentedon Jan 7, 2020
All layout-relative percentages are inherited as percentages. The problem is that I'm not sure any of them inherit by default, so you'd only see the effect if you were explicitly using the
inheritvalue, which is quite rare.This is probably close to a category feature: the only reason to resolve post-computed value is if you depend on layout, or have a special reason to want your resolution-reference to change as you inherit; (almost?) all of the former are non-inherited layout-related properties, while the latter is rare (like
currentcolor).benface commentedon Jan 7, 2020
Yes, sorry, I meant for inherited properties. I could only think of
font-sizewhich behaves likeline-height.jfkthame commentedon Jan 9, 2020
Looking back, I see that @fantasai explicitly mentioned the inconsistency with
line-heightback in #2165 (comment) (the original suggestion to use percentages).Personally, I agree with the assessment that "
line-height's use of percents is broken", and I don't think we should let that stand in the way of using percent more appropriately here.emilio commentedon Jan 13, 2020
I think it's still a bit weird that it's inconsistent with both
font-sizeandline-height, but...BillGoldstein commentedon Jan 15, 2020
Should this be accepted, I would hope word-spacing would be treated in similar fashion.
nuxodin commentedon May 31, 2021
The Working Draft "CSS Inline Layout Module Level 3" mentons:
I think this applies to all non-unitless values for
line-heightandletter-spacing, not just percentages.To fix this behavoir, i would love a property like
font-inheritancewith the possible values:length,unit[css-text-4] Add percentages to letter-spacing and word-spacing. #2165
fantasai commentedon Mar 11, 2022
Finally got around to merging CSS-TEXT-3 into CSS-TEXT-4. :/ Edits for this issue are now also in, so closing out.
benface commentedon Nov 18, 2023
I just wrote a kind of follow-up to this issue, for those who are interested: #9612