w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 667 forks source link

[css-text][css-text-4] Add a property to define when to stop trying to justify a line #1221

Open AmeliaBR opened 7 years ago

AmeliaBR commented 7 years ago

Rationale:

CSS Text Level 3 includes a rule for how to give up on justification if the text in a line cannot be stretched at all. But sometimes a line of text can be stretched, just not in an attractive way. The number of expansion opportunities cannot accommodate the amount of space that needs to be filled.

For a not-entirely hypothetical example, consider a paragraph like this:

There are two options for the patternContentUnits attribute: userSpaceOnUse (the default) or objectBoundingBox.

For reasons of accuracy, you do not want to introduce any hyphens or breaks in the code terms. But this sentence is part of a larger text which is justified for aesthetics.

When constrained to a narrow column of justified text, that might look something like this:

There   are   two   options   for   the 
patternContentUnits          attribute: 
userSpaceOnUse   ( the   default )   or
objectBoundingBox.

No matter how smart your justification algorithm, it's going to look bad.

Proposal:

A text-justify-limit property defines the point at which justification is deemed unacceptable for a given line of text. If the justification required for a line exceeds this limit, no justification is attempted, and the text is instead aligned according to text-justify-last (the same rule as if there were no justification opportunities in the line at all).

The value would be a percentage or a length.

Lengths would define the maximum amount of space that can be added at any single expansion point. In other words: divide the total amount of extra space that needs to be assigned by the total number of expansion points. If it is longer than the limit, don't try to justify. For inter-character justification, this is equivalent the maximum letter-spacing value.

Percentages would define the maximum increase in expandable characters, and would make sense for inter-word justification or character elongation. In other words, divide the total amount of extra space that needs to be assigned by the natural advance length of all expandable characters; if it is more than this percentage, don't try to justify. So text-length-limit: 100% would mean do not use justification if it would more than double the length of spaces (that is, increase them by more than 100%). This is equivalent to how percentages work for word-spacing.

Example

Looking again at the problematic paragraph, set in monospace font for easy math, with a 40ch target width:

There   are   two   options   for   the 
patternContentUnits          attribute: 
userSpaceOnUse   ( the   default )   or
objectBoundingBox.

The expansion lengths and percentages for each line are as follows:

With text-length-limit: 300%, the second line would be deemed un-justifiable, and the layout would look like this (assuming text-justify-last: auto):

There   are   two   options   for   the 
patternContentUnits attribute: 
userSpaceOnUse   ( the   default )   or
objectBoundingBox.

With text-length-limit: 1.9ch, the first two lines would be deemed un-justifiable. (Or, if the text layout didn't support adding extra space on the inside of the parentheses, all the lines would be un-justifiable.)

astearns commented 7 years ago

One issue I'd have with this feature is that I scan the shape of the 'corrected' example as two paragraphs.

AmeliaBR commented 7 years ago

@astearns That is an issue.

But it's less of an issue if you have extra blank space between paragraphs. Then it just looks like a forced line break in the same paragraph.

Like:

The scaling of pattern  tiles is deter-
mined by two attributes.

There   are   two   options   for   the 
patternContentUnits attribute: 
userSpaceOnUse   ( the   default )   or
objectBoundingBox.

The same options are  available for the
patternUnits attribute, but the default
is objectBoundingBox.

It's not beautiful, but it's better. Currently, our approach is "add some extra words or re-arrange the sentence until the justification isn't atrocious". But that only works for the print version, not for re-flowable media like ePub.

Another option would be to use the limit as a point to switch from inter-word to inter-character justification. I think some text layout tools essentially do that in their auto justification, anyway. That would need a more complicated value syntax, or new options for the text-justify property.


Edited to add: I did not intentionally add a <br> after "It's not beautiful, but it's better." That was just GitHub flavoured-markdown jumping in to prove my point about line breaks looking different from paragraphs in most styles.