w3c / csswg-drafts

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

CSS needs responsive typography design controls #7704

Open adamzea opened 2 years ago

adamzea commented 2 years ago

I hear this is the place to bring up feature requests for future CSS standards. Apologies if it isn't.

I think it’s about time the WWW started getting better typography controls in CSS. If you look at what typography designers can do in print applications like InDesign, the typography capabilities in CSS are still relatively primitive especially in the context of responsive design.

In the late 90’s as a beginning web designer, I would always have to tell my boss (a very experienced typography designer) that the things she wanted to do with type just wasn’t possible.  It’s now 2022 and many of those things still aren’t possible (though we do have web fonts now at least.) I’ve been waiting for decades for some of these typography controls to come to CSS standards and web browsers, so maybe if I describe them properly, someone will notice.

Runts

CSS still has no runt controls. A runt is when a paragraph ends with one word on one line. It’s very ugly. In print design software, we can fix this procedurally by selecting the last X number of characters using a GREP style and applying a no-break attribute to them. So if I set the last 15 characters to no-break in a paragraph, that will make the last 2 or 3 words stay together and therefore stay on the last line no matter what the container’s width becomes. This is not possible in CSS, but I think it should be.

The syntax could be something like:

p:nth-last-char(15) – selects the last 15 characters of a paragraph.

p:nth-first-char(15) – selects the first 15 characters of a paragraph

Then we could have something like below that applies the nowrap white-space attribute to the last 15 characters of a paragraph:

p:nth-last-char(15) { white-space: nowrap; }
/* keeps the last 15 characters of a paragraph from wrapping to another line */

One current work around for this is to add a BR break tag before the last two or three words in a paragraph and use media query breakpoints to apply “display: none” to the BR tag in instances where the paragraph width does not create widows on the last line. This requires manually adding the BR tag to content in the database and also requires manually measuring which media query breakpoints should activate or deactivate the work-around. That’s way too much work for something that can be automatic with a GREP rule in InDesign.

InDesign GREP Style dialogueWith InDesign, I can use GREP styles to apply a “nobreak” character style attribute to the last 15 characters in order to fix the widows in all paragraphs.

Orphans/Widows

Original Comments Deleted Can be controlled with https://drafts.csswg.org/css-break-3/#widows-orphans and https://drafts.csswg.org/css-break-3/#page-break-properties

Paragraph composer

Another issue in WWW typography is in the ragging of text on each line. There are no decent controls for this.  With InDesign, I can choose from different automatic paragraph composer settings and then I can tweak the minimum and maximum variations for things like word spacing, letter spacing, and glyph scaling.

Paragraph image with red line showing ragParagraph line ragging on the web often looks like this with huge imbalances between line lengths. This is extremely ugly in terms of typography design and reduces readability.InDesign's Justification style options dialogue.InDesign’s paragraph justification style options let me assign max/min word spacing, letter spacing, and glyph scaling percentages such that paragraph text will be adjusted accordingly.

The syntax could be something like:

p { paragraph-composer: multi-line-composer;

 word-spacing: mindesiredmax(80%, 100%, 110%);

letter-spacing: mindesiredmax(-5%, 0%, 5%);

glyph-scaling: mindesiredmax(90%, 100%, 110%); }

The CSS word-spacing property already exists, but doesn’t support any minimum/maximum variations within a multi-line paragraph composer. The CSS letter-spacing property also exists, but again doesn’t allow for variations within a paragraph according to the paragraph’s line ragging. There are no glyph scaling properties in CSS.

A balanced rag between lines in a paragraph is ideal in terms of typography and this is done by increasing or decreasing word spacing, letter spacing, and glyph scaling on a line-by-line basis in order to decrease the differences in line widths and make a more pleasing paragraph shape.

Sentence Spacing

Nobody does good sentence spacing in typography design anymore, so very few people probably even know about this aspect of typography design. Many people these days follow the convention of including only one space between sentences. For paragraphs with shorter sentences, this reduces the number of visual “pigeon holes” that may clutter the paragraph. However, with longer paragraphs filled with longer sentences, the single space between sentences makes the paragraph more difficult to read. Thus the smart way of typography design is to increase the space between sentences within longer paragraphs, while reducing the sentence space between shorter paragraphs.

See the advice given by Philip Luckombe in The History and Art of Printing (London, 1771):

Another rule that is inculcated into beginners, is, to use an m quadrat [i.e., an em-quad] after a Full-point [period]: but at the same time they should be informed, not to do it, where an Author is too sententious, and makes several short periods [sentences] in one Paragraph.  In such case the many Blanks of m-quadrats will be contemptuously called Pigeon-holes; which, and other such trifles, often betray a Compositor’s judgment, who may be a good workman else.

Also see: Why two spaces after a period isn’t wrong (or, the lies typographers tell about history) – Heraclitean River (archive.org)

I’m not sure what the syntax for a sentence spacing control should be as ideally we should have selectors to control shorter sentences separately from longer sentences. Perhaps the selectors can be defined by sentence character count.  Currently we have no CSS selector for sentences at all, nor do we have any attribute for controlling the space between sentences. Maybe something like

p:sentence-char-count(minmax(3, 30)) { sentence-space: 1em; }
/* selects sentences with 3 to 30 characters, applies 1em of space between sentences. /*
p:sentence-char-count(minmax(31, auto)) { sentence-space: 1.5em; }
/* selects sentences with minimum of 31 characters and no maximum, applies 1.5em of space between sentences. /*

Crissov commented 2 years ago

Widow and orphan control have been existing for a long time in CSS, not so long in browsers. https://caniuse.com/css-widows-orphans However, they work differently than in Indesign. You should probably explain how or why that’s insufficient.

adamzea commented 2 years ago

Ok, different people use the terms differently. I guess what I'm calling widows are sometimes also called "runts". Maybe I should use that term instead. CSS widows and orphans are line-based, not character based apparently. To fix runts (a single word on its own line at the end of a heading or paragraph), some number of characters at the end of the paragraph/heading need to be selected in order to apply a no-break white-space attribute. Alright, I'll edit the original to clarify.

astearns commented 2 years ago

To fix runts (a single word on its own line at the end of a heading or paragraph), some number of characters at the end of the paragraph/heading need to be selected in order to apply a no-break white-space attribute.

The fix for this problem is more related to the paragraph- or multiline-composer you also mention. It is usually better to change multiple line breaks to correct a short final line than to just make the last two lines shorter (but closer in length)

adamzea commented 2 years ago

The fix for this problem is more related to the paragraph- or multiline-composer you also mention.

Yes, absolutely! I'd love to be able to control that somehow. Runts are often a problem in single line headings that become 2 lines at certain container widths too. For those, I think a selector for the last X characters to apply the no-break attribute might work well in many cases.

faceless2 commented 2 years ago

PrinceXML has a non-standard extension to handle runts, I quite like the syntax: https://www.princexml.com/doc/prince-for-books/#fractional-widows

Re. your issue with ragged-right lines, you didn't mention text-align: justify - I presume you're aware of that?

SebastianZ commented 2 years ago

Before this discussion here goes on, I suggest to split the different requests up into several issues, so they can be discussed separately and it is easier for people to keep track of them.

Sebastian

adamzea commented 1 year ago

Re. your issue with ragged-right lines, you didn't mention text-align: justify - I presume you're aware of that?

Justify paragraph alignment is something different, but should also use the paragraph composer options, plus the character spacing, word spacing, and glyph scaling min/max values.
Justified paragraph text on the web currently adds space between words such that the first word and last word of each line are aligned to the width of the paragraph. On the web, this causes ugly "pigeon holes" of unbalanced white space within the paragraph. This is also bad typography design as the holes don't indicate anything of importance like the end of a sentence or new paragraph or such. They create distracting aesthetics and require the eye to move random distances in order to keep reading.

image

In the above screenshot, you can see Chromium on the right rendering some text with the "justify" alignment attribute. The same text on the left is in InDesign also with the "justify" alignment attribute but with a multi-line paragraph composer and some min/max settings for word spacing and character spacing. You'll notice the InDesign typography is a bit better than the web browser's typography since the spacing within each line is much more balanced due to the subtle variations in word and character spacing.

image

Now, in the above screenshot, some glyph scaling min/max values were added to the paragraph on the left. The changes in width to each letter are very subtle, but this makes for a much better paragraph shape with no massive "pigeon holes" at all. This is superior typography design than what is available in web browsers at the moment. However, sentence beginning/ends are not obvious in that paragraph, thus the need for a sentence spacing control in order to improve sentence skimming and readability.

All of these things would also be FANTASTIC for eBook readers to support, as eBook typography is pretty terrible, too.

Before this discussion here goes on, I suggest to split the different requests up into several issues, so they can be discussed separately and it is easier for people to keep track of them.

How shall I split them as different issues do you think? Like below perhaps?

  1. Responsive typography runts - select nth first/last characters
  2. Responsive typography paragraph line ragging - multiline composer, min/max character spacing, min/max word spacing, min/max glyph scaling
  3. Responsive typography select sentence based on sentence length - min/max selector based on character count
  4. Responsive typography sentence spacing - Control for increasing/decreasing space between sentences

All of them kind of go together as 2 can help with 1, 3 can help with 4, and 3 can help with 1.