Open Bug 125390 Opened 22 years ago Updated 2 years ago

CSS letter-spacing style extends after last letter of element with letter-spacing

Categories

(Core :: Layout: Text and Fonts, defect, P3)

defect

Tracking

()

Future

People

(Reporter: brad, Unassigned)

References

(Depends on 2 open bugs, )

Details

(Keywords: testcase)

Attachments

(2 files)

Given the following input:

<html><h1>Bra<span style="letter-spacing: 1em">dl</span>ey</h1></html>

With Mozilla 2002021203, I get "Brad l ey", whereas with IE6 I get "Brad ley". 
I believe that IE is the one that's right here.

letter-spacing is the only way to really do proper character kerning, but this
problem makes using it for this purpose difficult.
->Layout, although I'm not sure what the correct behavior really should be. 
This proposal is reasonable though, except it might do weird things if a single
word has large letter spacing (which would be better if we put half the
letter-spacing around each character).
Assignee: dbaron → attinasi
Component: Style System → Layout
Keywords: css1
QA Contact: ian → petersen
Mozilla is behaving properly, at least according to the CSS2 spec.  Section 9.1
of the CSS2 specification says, "The visual formatting model does not specify
all aspects of formatting (e.g., it does not specify a letter-spacing
algorithm). Conforming user agents [p. 32] may behave differently for those
formatting issues not covered by this specification."

Unfortunately, Mozilla's current interpretation of the letter-spacing style
attribute makes kerning letters difficult.  For example, I don't know if it's
possible to have the letters "To" in the word "Ton" kerned and have it display
properly on both IE and Mozilla.  In Mozilla, I'd apply the attribute to only
the "T"; in IE, I'd apply it to "To".
Confirming in the Feb 25th build.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Priority: -- → P3
Target Milestone: --- → Future
Whiteboard: [CSS1-5.4.2]
Reconfirmed using FizzillaCFM/2002070913. Setting All/All.
OS: Windows 2000 → All
Hardware: PC → All
Attached file Testcase
Keywords: testcase
Possible dup of/related to bug 102016 or bug 93168?
IMHO we should do the half-either-side option. It makes the most sense in
scenarios such as this and with things like bidi.
Depends on: 102016
Since this isn't actually a violation of the CSS1 spec, removing keyword &etc.
Assignee: attinasi → font
Component: Layout → Layout: Fonts and Text
Keywords: css1
QA Contact: petersen → ian
Whiteboard: [CSS1-5.4.2]
proposal:

letter spacing should always go after the letter (after in the BIDI-after sense).

We should not add this space if:

1) the frame is the last frame in the line (LTR text) or the last frame in the
line (RTL text)

2) the frame has right padding (LTR text) or left padding (RTL text)

This fixes issues with right-alignment of spaced LTR text, and still gives web
authors precise control over kerning on a per-letter basis if needed. However,
it doesn't "fix" the original bug report, which I believe we render correctly.
after a lot of thought about this, I firmly believe that letter-spacing should
apply ONLY to 2 or more letters within a given span, ignoring both the preceding
and trailing ends. setting a letter-spacing property on a single letter should
have no effect.
if you think about it, this is how normal text is treated. a single letter has
no spacing set to it. placed within a cell, it's edges will rest flush against
the cells edges. if you place a char next to it, then the 2 chars together will
have a space between them. this is the spacing that you would be increasing
and/or decreasing. not a "trailing space" type of spacing, not a "half amount on
either side", and no allowing letter-spacing on a single letter, which leads to
HORRIFIC cases of trying to resolve conflicts between differing adjacent values
set on single letters or even spans of letters.
this is a perfectly logical and common sense solution to the problem.
here are some examples:

&lt;span style="letter-spacing:1em"&gt;a&lt;/span&gt;&lt;span
style="letter-spacing:1em"&gt;b&lt;/span&gt;

should be ignored, resulting in "ab" as per normal display.


&lt;span style="letter-spacing:1em"&gt;ab&lt;/span&gt;&lt;span
style="letter-spacing:1em"&gt;cd&lt;/span&gt;

should result in "a bc d", as the spacing WITHIN EACH SPAN is set to set a 1em
spacing between the letters WITHIN EACH SPAN. this setting should not effect
those letters relation to letters outside the span, or a bounding cell etc. that
 property would be PADDING to be set on the span (internally) or MARGIN
(externally).

with this simple solution, I do not see any unsolvable cases, or complex
situations to need complex solutions etc. no grey area. and this fits with the
behavior of many other aspects of the rendering engine, not only for text
rendering, but other elements as well.
There are some serious flaws in the above proposals:

Re comment 9: discontinuities are disturbing to authors.  If 1 pixel of padding
causes there to be less space than 0 pixels of padding, that will lead to confusion.

Re comment 10: 'letter-spacing' is an inherited property.  Consider:
  <h2 style="letter-spacing: 0.3em">The <abbr title="...">ABC</abbr>'s work</h2>
Do you want there to be less space between "C" and "'" than between any other
letters?
(I think the correct thing to do is put half the letter spacing on each side of
each letter.)
can someone explain to me why they think that letter-spacing should have any
effect on content outside of a span of letters? we're dealing with text here,
and to be consistent with the current behavior of text, we should ignore
anything outside of a given span WITH REGARD TO letter-spacing. padding and
margin both seem perfectly adequate in addressing the leading or trailing end of
such content.
this "half on each side" seems moot in regards to what I'm proposing. you still
shouldn't be affecting content outside the span... this behavior of affecting
content outside the span is what's causing this "bug" already. adding a trailing
space after the end of the span is WRONG. it's not supposed to be there. just
because you're splitting that FLAW in half and having half of it on both ends
doesn't make it any better and will still require frustrating work-arounds. the
CSS specification itself calls letter-spacing "the space between characters"
(not the space between a character and some other object) and should only affect
the letters INSIDE THE SPECIFIED SPAN with no leading or trailing space. the
entire problem here revolves around people insisting on this value affecting
content outside the span, which as I've said many times now, seems perfectly
suited to the already existing padding and margin properties.
now it's completely possible I'm missing something here, or not grasping some
fundamental concept... in which case I would appreciate some enlightenment.
otherwise, the rest of this debate is pointless. 

span { letter-spacing:1em;}

ab<span>cde</span>fg
abc d efg

ab<span style="margin:0 1em;">cde</span>fg
ab c d e fg

this seems to me to allow proper control over letter-spacing etc without causing
any inconsistencies or ambiguous conditions etc.

again, please explain to me if I am somehow missing something here.
Justin: There was so much rhetoric in your last comment (comment 13) that I
couldn't actually work out what you were proposing.

Could you explain the proposal on its own terms, not describing it relative to
other implementations or proposals? Please take into account the point in
comment 11 regarding your proposal in comment 10, which as far as I can tell is
still an issue in your latest proposal. (Note that this is the most common case.)

For what it's worth, I agree with dbaron; letter-spacing should IMHO be rendered
as half on each side of the letter, except at the start and end of the line.
in response to #14, I think mozilla also incorrectly renders your example.
I don't see how my proposal doesn't handle this situation... I'll post a URL to
an image showing 2 things, and explain here what I'm describing.
http://acherondesign.com/~largo/letter-spacing.png
in what I proposed, considering that all the characters within the specified
element are supposed to have spacing between them, this is rendered (almost)
correctly... the issue here seems to lie with the <abbr> tag continuing on with
the letter spacing rather than the letters themselves. this looks to me like yet
another flaw with the implementation. where it seems that your (collective)
proposal of spacing half on either side is closer to a better solution in
regards to this specific case -as implemented-, I don't see why the <abbr>
doesn't stop at either edge of the letters ABC. is there any spec that states
that it has to also encompass the letter spacing as well?

(I don't think I need to point out that the above example still tacks on the
extra space at the end, so that in something like an inline div with a border,
even with the text-align:center, there is still an "extra space" at the end.)
I'm sorry, I am having a great deal of difficulty actually understanding exactly
what it is you are proposing. Could you tersely describe the algorithm? As in,
describe your proposal in no more than 3 lines, without referring to any other
proposals or comparing it to any implementations, and without mentioning
previous comments, examples, or code snippets in this bug.

Thanks!
in a specified span of characters, only apply letter-spacing between characters
if there are 2 or more characters within the span.

letter-spacing should be ignored on the leading and trailing end of the span
even if there are other characters adjacent outside of the span.

padding and/or margin can be used to set left and/or right padding/margins to
the span of characters to add padding/margins in relation to other content.
another "test case"

http://acherondesign.com/~largo/letter-spacing-test.png

interested in comments on this.
The "Re comment 10:" part of comment 11 explains why that won't work.

(Being consise is good.  Otherwise nobody will read what you write.)
...although I guess you could work around that problem by putting the full
letter spacing before/after any children.  That might work.  But it would be a
good bit harder to implement, and I'm really not interested in anything that
might make the code in question any more complicated, since it's far too
complicated already (needlessly).
David, could you explain to me a little more clearly what you mean? I don't understand 
how your "re comment #10" in comment #11 explains why my proposal won't work. 
also, which comment are you referring to specifically? 
also, what exactly do you mean about the children? I'm not sure what children you're 
referring to. 
thanks. (sorry if I'm being ignorant) 
 
Justin: regarding comment 17: Aha! Thanks. That made a lot more sense.

The problem that David pointed out is with this:

   <span>aaa<span>bbb</span>ccc</span>

According to your description, if you said:

   span { letter-spacing: 1em; }

...then the rendering would be:

   A A AB B BC C C

...which is bad, since the addition of an identically styled inline element
child (the inner <span> here) should not make any visible difference to the
resulting rendering.
actually, if you look at what I posted in comment #18, you'll see that I was
under the impression that as the letter-spacing property is inherited, that it
would still render as you say it should. the image in comment #18 explains.
Your description in comment 17 does not match that.
I believe it does. those characters are still within the span. due to it's
inherited nature.
perhaps I should specify a fourth line to #17 clarifying that.

none the less, I thought #18 would make it clear how I thought it should behave.
my apologies.
let me rephrase that...
the characters adjacent to the child span are still within the parent span, and
due to the inherited nature of the letter-spacing property, the spacing between
B and C should still be applied, as it would still cover all the characters if
not for the child span taking precedence -only between- C and D.

another image to illustrate this follows:
http://acherondesign.com/~largo/letter-spacing-2.png
For:

   span { letter-spacing: 1em; }
   <h1><span>T</span><span>E</span><span>S</span><span>T</span></h1>

...the rendering with your suggestion would be:

   TEST

...instead of:

   T E S T

...as it would be with the half-on-each-side idea. I think I prefer the latter 
rendering for that particular case.
(In reply to comment #27) I don't understand why someone would do a <span> for
each letter. Having a <span> for the whole thing is generally what happens. If
you really have to have one for each letter, enclose it all in a <span> --
that's what I'd expect to have to do for this behavior.

The current proposal (with half on each side) makes no allowances, as far as I
can tell, when the letters in question end a line. It may not be noticeable if
text is left-aligned, but when right-aligned, it staggers it so that it looks
like somebody put a [letter-spacing]-wide space. Already a problem, and when
letter-spacing is 15px, 7px and 15px look just as ugly, especially when
something nearby shows the true right margin.
My sig on a forum. This is an example of the problems caused by the current
implementation and the half-spacing proposal. The spaces after
"come/create/:ize" are irregular and don't belong there. Looks fine in IE6.
> The current proposal (with half on each side) makes no allowances, as far as I
> can tell, when the letters in question end a line.

The full proposal is "put half the letter-spacing on either side of the letter, 
except at the edges of the line".
(In reply to comment #30)
> > The current proposal (with half on each side) makes no allowances, as far as I
> > can tell, when the letters in question end a line.
> 
> The full proposal is "put half the letter-spacing on either side of the letter, 
> except at the edges of the line".

But wouldn't this still have the same "problem" as the other proposal with:

span { letter-spacing: 1em }
<span>T</span><span>E</span><span>S</span><span>T</span>

rendering as TEST.

And how would it handle:

<span style="letter-spacing: 1em">T<span style="letter-spacing:
2em">ES</span>T</span>

Would there be .5 em between T and E, or no spacing, or 1em? From what I
understand it would be .5em which would be counter intuitive since the
letter-spacing is only being increased.
"put half the letter-spacing on either side of the letter, except at the edges 
of the line".

> span { letter-spacing: 1em }
> <span>T</span><span>E</span><span>S</span><span>T</span>

That would render as "T E S T" since each letter would have 0.5em letter spacing 
on either side, except at the edges.


> <span style="letter-spacing: 1em">T<span style="letter-spacing:
> 2em">ES</span>T</span>

There would be 1.5em space between the T and the E, 2em between the E and the S, 
and 1.5em between the S and the final T: "T E  S T".


> Would there be .5 em between T and E, or no spacing, or 1em?

1.5em. Half of the T's letter-spacing from the T's right side, and half of the 
E's letter spacing from the E's left side.
> That would render as "T E S T" since each letter would have 0.5em letter spacing 
> on either side, except at the edges.

Gotcha, I thought by edges you meant the edge of each span. This seems like a
pretty good solution. Although I don't think this will solve the original
poster's problems with kerning. After thinking about it for a while I don't
think there's really any perfect way to do it which will accomodate all desired
uses of letter-spacing (unless css was expanded to have stuff like
letter-spacing-right, letter-spacing-left, letter-spacing-outer,
letter-spacing-inner...).

I still think that a proper usage of letter-spacing would be to reduce or expand
the spacing between just two adjacent letters, which wouldn't be possible with
the current suggestion.
another realistic test case is here: http://www.reitter-it-media.de/index_mozbug.html

The W3C CSS spec clearly states that letter-spacing controls the space BETWEEN the letters, and not to 
the right (or left) of letters: http://www.w3.org/TR/REC-CSS1#letter-spacing


The W3C specification defines presentation, it doesn't define an algorithm.
Summary: CSS letter-spacing style extending too far → CSS letter-spacing style extends after last letter of element with letter-spacing
Assignee: layout.fonts-and-text → nobody
QA Contact: ian → layout.fonts-and-text
We should fix this by implementing the rules in http://www.w3.org/TR/css3-text/#letter-spacing .

That said, it looks like there's work ongoing in bug 299943.
I just stumbled over this issue recently[1] having this as test case:

data:text/html,<input maxlength="5"
style="box-sizing:content-box;width:17.1ch;border:1px solid
black;background-image:repeating-linear-gradient(to right, transparent,
transparent 1.72ch, gray 1.72ch, gray 1.82ch);padding:0
0.4ch;font-family:monospace;font-size:6ch;letter-spacing:0.8ch;"
value="0123456789">

My idea to solve this is similar to the one mentioned by Steven in comment 33. That is, introduce some syntax to allow to change the behavior. Therefore I proposed[2] to extend letter-spacing to this:

  letter-spacing: [ normal | <length> ] [ inside || [ outside | inline-start | inline-end ] ]?

Sebastian

[1] https://lists.w3.org/Archives/Public/www-style/2016Feb/0012.html
[2] https://lists.w3.org/Archives/Public/www-style/2016Feb/0018.html
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.