Use ch units instead of em
Since the goal is to ensure a certain number of characters per line, ch units should work better than em. From 7 CSS Units You Might Not Know About:
The units
exandch, similar toemandrem, rely on the current font and font size. However, unlikeemandrem, these units also rely on the font family, as they are determined based on font-specific measures.
The
chunit, or the character unit, is defined as being the ... width of the zero character,0. Some very interesting discussion about what this means can be found on Eric Meyers's blog, but the basic concept is that, given a monospace font, a box with a width of ...40chcan always contain a string with 40 characters in that particular font.
Notes on Wikipedia's Line length article are rather confusing/inconclusive, but it looks like a default of 60 CPL, with a minimum of 40ch and a max of 80ch is consistent with most, if not all, of the proposals.
Note: the ch unit is supported by all major browsers.
Turns out the actual average character width in a proportional (i.e. non-monospaced) font will typically be shorter than the width of the zero character. We'd need to multiply the width (say, 60ch) by that ratio to make the final result accurate. Unfortunately, that ratio depends on the font used.
For the current font (Palatino), the ratio can be calculated by creating a relatively long line containing a typical distribution of characters. I used the Just Another Foundry generator in the neutral setting to generate the following 1000-character text:
Ini Carthe descien ressen carwala sica posati, girch folens et mor et poread ettu, set Intske hen austre koso beede egre bla vuldio. Ind. Behas amainve lancen parglo, 'Freerd; elstin Norno mode inerit serman Bru hunneva le 11 Driat ari ner le mapria pre tati mille be ileurs posta, niring resta exture (184 Neur, tal eiefec mint cy onar ganter, a mares. Hel ista ospock hee. Augs ette (recivo cresva, Bul Infor cosen puntri patim demmen Sta mes estli, werair nock, des palded orin eteste que omeint dighel ruch, by vona ridan Ang to nollect des ermagn den voling, poccun tossal tation daye milona, crille ont isonto bed Arcurt, kassen paribra chor evelma kome exce, eimene cou per vor homand, na un densto ficans wer fes makter lorme ode st ye rety per alung ing tich an dempun korbat sche kande pacons. Vent, demod al pardla nands intrit apeda, wicare spoces. Sinom Chiber sio herst Ante leniff sto nut stecti acarar grourbi vologra: tascat iffe edes, uno Ins ens ausade aress pantle hastie tratace.
If I then use a paragraph of 1000 zeros and one with the text above:
<p style="width: 1000ch">
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
</p>
<p style="display: ruby">
Ini Carthe descien ressen carwala sica posati, girch folens et mor et poread ettu, set Intske hen austre koso beede egre bla vuldio. Ind. Behas amainve lancen parglo, 'Freerd; elstin Norno mode inerit serman Bru hunneva le 11 Driat ari ner le mapria pre tati mille be ileurs posta, niring resta exture (184 Neur, tal eiefec mint cy onar ganter, a mares. Hel ista ospock hee. Augs ette (recivo cresva, Bul Infor cosen puntri patim demmen Sta mes estli, werair nock, des palded orin eteste que omeint dighel ruch, by vona ridan Ang to nollect des ermagn den voling, poccun tossal tation daye milona, crille ont isonto bed Arcurt, kassen paribra chor evelma kome exce, eimene cou per vor homand, na un densto ficans wer fes makter lorme ode st ye rety per alung ing tich an dempun korbat sche kande pacons. Vent, demod al pardla nands intrit apeda, wicare spoces. Sinom Chiber sio herst Ante leniff sto nut stecti acarar grourbi vologra: tascat iffe edes, uno Ins ens ausade aress pantle hastie tratace.
</p>
...I can measure the length of both paragraphs and get a pretty accurate measure of Palatino's average character width. The result is 8000px for the first paragraph, and 6991.63px for the second paragraph, which leads to a ratio of 0.87395375.
Therefore, for Palatino font I'd need to specify the width as:
body { max-width: calc(60ch * 0.87395375); }
For reference, the numbers for Libertinus Serif are 6470.77 / 7433.33, leading to a ratio of 0.870507565. Pretty similar, hmmm 🤔
(Also, when implementing this, don't forget to account for the 1em padding on both sides!)